Search code examples
javahibernate-envershibernate-5.x

Why is this Hibernate bootstrap code failing to start up, when Envers is turned on?


I am using Hibernate 5.2.0.

This code works (Envers is turned off):

public static SessionFactory buildSessionFactory()
    {
    StandardServiceRegistryBuilder standardServiceRegistryBuilder 
        = new StandardServiceRegistryBuilder();

    standardServiceRegistryBuilder
          .applySetting("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect")
          .applySetting("hibernate.connection.driver_class", "com.mysql.jdbc.Driver")
          .applySetting("hibernate.connection.url", "jdbc:mysql://localhost:3415/test")
          .applySetting("hibernate.connection.username", "myusername")
          .applySetting("hibernate.connection.password", "mypass123")
          .applySetting(AvailableSettings.HBM2DDL_AUTO, "create")
          .applySetting(AvailableSettings.TRANSACTION_COORDINATOR_STRATEGY, "jdbc")
          .applySetting(AvailableSettings.ISOLATION, String.valueOf(Connection.TRANSACTION_READ_COMMITTED))

          // TURN OFF ENVERS:
          .applySetting(EnversService.INTEGRATION_ENABLED, false)
          .applySetting(EnversIntegrator.AUTO_REGISTER, false);

    standardRegistry = standardServiceRegistryBuilder.build();
    MetadataSources metadataSources = new MetadataSources(standardRegistry);

    Set<Class> classes = getAllPersistableClasses();
    classes.forEach(metadataSources::addAnnotatedClass);

    MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder();
    metadataBuilder.applyImplicitNamingStrategy(new MyNamingStrategy());

    // It FAILS HERE WHEN ENVERS IS TURNED ON:
    Metadata metadata = metadataBuilder.build(); 

    SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder();
    sessionFactoryBuilder.applyInterceptor(new MyInterceptor());

    return sessionFactoryBuilder.build();
    }

However, when I turn Envers on:

.applySetting(EnversService.INTEGRATION_ENABLED, true)
.applySetting(EnversIntegrator.AUTO_REGISTER, true)

It then fails when the following line builds the metadata:

Metadata metadata = metadataBuilder.build();

It fails with:

org.hibernate.boot.MappingException: Unable to perform unmarshalling at line number 0 and column 0. Message: null : origin(envers)

This is the complete stacktrace:

org.hibernate.boot.MappingException: Unable to perform unmarshalling at line number 0 and column 0. Message: null : origin(envers)
    at org.hibernate.boot.jaxb.internal.AbstractBinder.jaxb(AbstractBinder.java:177)
    at org.hibernate.boot.jaxb.internal.MappingBinder.doBind(MappingBinder.java:61)
    at org.hibernate.boot.jaxb.internal.AbstractBinder.doBind(AbstractBinder.java:102)
    at org.hibernate.boot.jaxb.internal.AbstractBinder.bind(AbstractBinder.java:57)
    at org.hibernate.envers.boot.internal.AdditionalJaxbMappingProducerImpl$1.addDocument(AdditionalJaxbMappingProducerImpl.java:92)
    at org.hibernate.envers.configuration.internal.EntitiesConfigurator.configure(EntitiesConfigurator.java:111)
    at org.hibernate.envers.boot.internal.EnversServiceImpl.doInitialize(EnversServiceImpl.java:152)
    at org.hibernate.envers.boot.internal.EnversServiceImpl.initialize(EnversServiceImpl.java:117)
    at org.hibernate.envers.boot.internal.AdditionalJaxbMappingProducerImpl.produceAdditionalMappings(AdditionalJaxbMappingProducerImpl.java:99)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:288)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83)
    at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:418)
    at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:87)
    at Bd.RelacionadosAoHibernate.UtilHibernate.createSessionFactory(UtilHibernate.java:470)
    at Bd.RelacionadosAoHibernate.UtilHibernate.<clinit>(UtilHibernate.java:79)
    at Aplicativo.InitAplicativoBdHttp.executaInicializacao_Hibernate(InitAplicativoBdHttp.java:108)
    at Aplicativo.InitAplicativoBdHttp.inicializaBancoDeDados(InitAplicativoBdHttp.java:29)
    at Aplicativo.InitAplicativo.inicializa(InitAplicativo.java:16)
    at Http.Sessao.ListenerDeAplicacao.<clinit>(ListenerDeAplicacao.java:24)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at java.lang.Class.newInstance(Class.java:433)
    at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:121)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4651)    
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5167)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1648)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:463)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:413)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1466)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1307)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1399)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:828)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:323)
    at sun.rmi.transport.Transport$1.run(Transport.java:178)
    at sun.rmi.transport.Transport$1.run(Transport.java:175)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:174)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:557)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:812)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:671)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Caused by: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.stream.XMLStreamException: ParseError at [row,col]:[67,50]
Message: Invalid byte 2 of 2-byte UTF-8 sequence.]
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:470)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:448)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:420)
    at org.hibernate.boot.jaxb.internal.AbstractBinder.jaxb(AbstractBinder.java:171)
    ... 67 more

Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[67,50]
Message: Invalid byte 2 of 2-byte UTF-8 sequence.
    at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:596)
    at com.sun.xml.internal.stream.XMLEventReaderImpl.peek(XMLEventReaderImpl.java:276)
    at javax.xml.stream.util.EventReaderDelegate.peek(EventReaderDelegate.java:104)
    at org.hibernate.boot.jaxb.internal.stax.BufferedXMLEventReader.peek(BufferedXMLEventReader.java:96)
    at javax.xml.stream.util.EventReaderDelegate.peek(EventReaderDelegate.java:104)
    at org.hibernate.boot.jaxb.internal.stax.HbmEventReader.peek(HbmEventReader.java:47)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXEventConnector.handleCharacters(StAXEventConnector.java:164)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXEventConnector.bridge(StAXEventConnector.java:126)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:445)
    ... 69 more

05-Jun-2016 23:49:27.093 SEVERE [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start. Full details will be found in the appropriate container log file

Any ideas? Thanks.


Solution

  • I found the problem, and opened this bug issue:

    https://hibernate.atlassian.net/browse/HHH-10811

    This bug prevents some valid Java identifiers from being used as persisted fields names, and only when Envers is used.

    An example problem is an audited class (source code in UTF-8) containing a boolean field called "seÉfinal", since the character "É", an accented version of character "E", results in a parsing error: "Invalid byte 2 of 2-byte UTF-8 sequence". Many character will fail, for example: áéíóúãõñàèçÁÉÃÇ etc.

    Most commonly this is due to feeding ISO-8859-x (like Latin-1) but the XML parser thinking it is getting UTF-8 (or vice-versa). For example, certain sequences of Latin-1 characters (two consecutive characters with accents or umlauts) form something that is invalid as UTF-8, and specifically such that based on first byte, second byte has unexpected high-order bits.

    Workaround is renaming all fields, so that they don't contain non-English letters.