Hibernate 5.2.10 on WebSphere


#1

Team,
I upgraded my project to use hibernate 5.2 and i am getting a parsing issue for hbmxml files on websphere only, it works fine on other environments.

I am getting the following error
Error accessing stax stream : origin()

org.hibernate.boot.MappingException: Error accessing stax stream : origin(<unknown>)
	at org.hibernate.boot.jaxb.internal.AbstractBinder.seekRootElementStartEvent(AbstractBinder.java:141)
	at org.hibernate.boot.jaxb.internal.AbstractBinder.doBind(AbstractBinder.java:101)
	at org.hibernate.boot.jaxb.internal.AbstractBinder.bind(AbstractBinder.java:84)
	at org.hibernate.boot.jaxb.internal.JaxpSourceXmlSource.doBind(JaxpSourceXmlSource.java:29)
	at org.hibernate.boot.MetadataSources.addDocument(MetadataSources.java:409)
	at org.hibernate.cfg.Configuration.addDocument(Configuration.java:462)

The generated xml file looks like this

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                                   "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class entity-name="cregion" lazy="true"
        name="cfc.cfsuite.orm.di.crud.cud.entitynew.basictest.cregion" table="Region">
        <id name="RegionID" type="int">
            <column length="10" name="RegionID"/>
        </id>
        <property name="RegionDescription" type="string">
            <column name="RegionDescription" not-null="true"/>
        </property>
    </class>
</hibernate-mapping>

The only difference between earlier version[Hibernate 4.3] and new version[Hibernate 5.2] is that the first delimiter in class name has been changed from : to . .

So earlier my class name was name=“cfc:cfsuite.orm.di.crud.cud.entitynew.basictest.cregion” and now it has been changed to name=“cfc.cfsuite.orm.di.crud.cud.entitynew.basictest.cregion”.

This change was done because Hibernate 5 uses JAXP due to which we were having parsing issue if the name contains : as delimiter so we changed it to .. This worked well on all other environments but is failing in websphere 9.

I tried lookig for this on StackOverflow and have validated that *.hbmxml file generation is proper and the dtd are also accessible from the environment.

Any help in this regard will be highly appreciated.


#2

Maybe you are missing the <?xml version="1.0"?> line:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

#3

Tried using that but that didn’t helped either. Also i earlier forgot to paste the inner exception from WebSphere, i am getting this exception

Caused by: java.lang.IllegalArgumentException: local part cannot be "null" when creating a QName
	at javax.xml.namespace.QName.<init>(Unknown Source)
	at com.ibm.xml.xlxp2.api.stax.DOMStreamReaderImpl.createQName(DOMStreamReaderImpl.java:1086)
	at com.ibm.xml.xlxp2.api.stax.DOMStreamReaderImpl.getName(DOMStreamReaderImpl.java:976)
	at com.ibm.xml.xlxp2.api.stax.XMLInputFactoryImpl$XMLStreamReaderProxyImpl.getName(XMLInputFactoryImpl.java:417)
	at com.ibm.xml.xlxp2.api.wssec.WSSXMLInputFactory$WSSStreamReaderProxy.getName(WSSXMLInputFactory.java:55)
	at com.ibm.xml.xlxp2.api.stax.XMLEventReaderImpl.createStartElementWithAttributes(XMLEventReaderImpl.java:591)
	at com.ibm.xml.xlxp2.api.stax.XMLEventReaderImpl.createEvent(XMLEventReaderImpl.java:397)
	at com.ibm.xml.xlxp2.api.stax.XMLEventReaderImpl.createNextEvent(XMLEventReaderImpl.java:367)
	at com.ibm.xml.xlxp2.api.stax.XMLEventReaderImpl.peek(XMLEventReaderImpl.java:162)
	at javax.xml.stream.util.EventReaderDelegate.peek(Unknown Source)
	at org.hibernate.boot.jaxb.internal.stax.BufferedXMLEventReader.peek(BufferedXMLEventReader.java:96)
	at org.hibernate.boot.jaxb.internal.AbstractBinder.seekRootElementStartEvent(AbstractBinder.java:137)

#4

Maybe it’s related to IBM WebSphere, not Hibernate.

You can try with a test case using this template and load your mapping files with the default Java XML engine.

Better ask the question on the IBM forums since it looks like a WebSphere issue.


#5

Sure will checkout, i have already tested the hbmxml on other environments and that works, its just that i was getting this specifically on WebSphere. I think it should be related to WebSphere environment, i will check on their forums.

Thanks a lot for your quick responses. Appreciate it :grinning:


#6

So I suspect the issue lies within the Stax implementation of Websphere.

I would add a breakpoint inside this loop of AbstractBinder to see which element causes the error:

while ( rootElementStartEvent != null && !rootElementStartEvent.isStartElement() ) {
   // ...
}

That might help you to narrow down the issue and find something about it on the Internet.


#7

I actually tried it out by attaching the hibernate source code.

  	while ( rootElementStartEvent != null && !rootElementStartEvent.isStartElement() ) {
  		staxEventReader.nextEvent();
  		rootElementStartEvent = staxEventReader.peek();
  	}

Problem is with staxEventReader.peek() function, when it tries to read the following lines:

<hibernate-mapping>
    <class entity-name="cregion" lazy="true"
        name="cfc.cfsuite.orm.di.crud.cud.entitynew.basictest.cregion" table="Region">

on checking a bit about stax parser i found that this parser works in the form of reading events, accordingly convert it to namespaces and then call the following function
public QName(String namespaceURI, String localPart, String prefix) , where the localPart is coming as null.

A couple of posts on StackOverflow [https://stackoverflow.com/questions/10312514/local-part-cannot-be-null-when-creating-a-qname/28316237] identified setting the documentFactory.documentBuilderFactory.setNamespaceAware(true) etc. I tried out the following options but nothing helped out so far. I am still working on it.

Thanks for the help :slight_smile: .Let me know if you want me to try out some other things.


#8

The localPart is the name of the element so it should for sure be not null.

The code above is used to get to the root element so it should only try to read the first line:

<hibernate-mapping>

Try to see what’s not null in the QName it tries to create (not sure you have the source of the Stax implementation though :/): it might help to understand what’s going on. You should at least be able to add a breakpoint in javax.xml.namespace.QName.

If it ends up being a bug in the Stax layer of Websphere, a solution might be to add another (better) implementation in your classpath.


#9

It should also never call that QName constructor when parsing a XML based on a DTD not using any namespace…

Try to figure out how to configure WebSphere to bypass its XML libs and use the JRE installed ones (most probably that’s what other environments where your code is working are doing…)

FYI under WebLogic to solve similar issue (XML libs supplied by container not working as expected…) I did the following:
in weblogic.xml, In the prefer-application-resources section
<wls:resource-name>META-INF/services/com.sun.xml.ws.spi.db.BindingContextFactory</wls:resource-name> <wls:resource-name>META-INF/services/javax.xml.bind.JAXBContext</wls:resource-name>
and in META-INF/services/com.sun.xml.ws.spi.db.BindingContextFactory
com.sun.xml.ws.spi.db.BindingContextFactory

and in META-INF/services/javax.xml.bind.JAXBContext
com.sun.xml.bind.v2.ContextFactory


#10

Some more debugging leads me to this point. In AbstractBinder.java, the following code-snippet

	private XMLInputFactory buildStaxFactory() {
		XMLInputFactory staxFactory = XMLInputFactory.newInstance();
		staxFactory.setXMLResolver( xmlResourceResolver );
		return staxFactory;
	}

returns WSSXMLInputFactory on WebSphere while for others it returns WSTXInputFactory as staxFactory value and that is where things differ.


#11

okay so somehow i got it working, the problem was with the default stax implementation in Websphere. For more details one can refer to this post http://veithen.github.io/2013/10/02/broken-by-design-websphere-stax.html

I added the following flag -Djavax.xml.stream.XMLInputFactory=com.ctc.wstx.stax.WstxInputFactory and copied woodstox-core-asl-4.4.1.jar which got it working.

Thanks folks for all the help :slight_smile:


#12

Thanks for the follow-up!