Initializing JAXB for unmarshalling to external class definitions - class

I am using Axis to generate client side service classes, and I would like to use those classes within the same runtime as the generation. I have implemented the axis generate and compile successfully. However, using reflection to instantiate and call the generated classes (with custom class loader), the jaxb unmarshall keeps returning a null (I have verified correct response xml from the service call).
It seems there needs to be some sort of initialization of the jaxb context when loading in classes in realtime (not on the classpath) from a custom classloader.
Any suggestions/insight?

Related

EclipseLink-Moxy Unable to load custom DomHandler class while instantiating JAXB context

I am using Eclipselink Moxy Implementation of JAXB in my project to map complex XML to String Object using XmlAnyElement.
For this I have implemented DomHandler named as LayoutHandler.
I am using JAXB for resteasy web services deployed in JBoss 6.
I am facing Below issue intermittently -
Exception [EclipseLink-50033] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b):
org.eclipse.persistence.exceptions.JAXBException
Exception Description: The DomHandlerConverter for DomHandler
[com.**.LayoutHandler] set on property [layoutXml] could not be
initialized.
Internal Exception: java.lang.ClassNotFoundException:
com.**.LayoutHandler from
BaseClassLoader#5c0b3ad0{vfs:///*/*/jboss-server/server/all/deployers/resteasy.deployer}
While EclipseLink Moxy is instantiating JAXBContext using JAXBContext.newInstance(classes, properties)
After spending some time in debugging and analyzing the issue I could figure out that ClassLoader of resteasy is getting used to load LayoutHandler class instead of my application class loader(vfs://///jboss-server/server/all/deploy/app_name.ear/app_name.war/) which is causing the issue as its unable to find the LayoutHandler class.
When I bounce the server, issue is getting resolved so I am unable to find out the exact root cause. Any help will be appreciated.
Further debugging into org.eclipse.persistence.jaxb.JAXBContextFactory revealed that below two classes are getting passed to createContext() method of JAXBContextFactory -
org.jboss.resteasy.plugins.providers.jaxb.JaxbCollection
com.**.Model_class
public static javax.xml.bind.JAXBContext createContext(Class[] classesToBeBound, Map properties) throws JAXBException {
ClassLoader loader = null;
if (classesToBeBound.length > 0) {
loader = classesToBeBound[0].getClassLoader();
}
return createContext(classesToBeBound, properties, loader);
}
In above method classloader of first class is getting used to load the custom DomHandler later on.
When first element in array is model class at that time code is working fine as application context class loader is getting used but when the first element in array is JaxbCollection rest easy context class loader is getting used and its throwing mentioned exception.
This issue is occurring intermittently as order of elements in array is varying which might be due to the use of HashSet to hold the elements of type Class by caller of this method which is passing the classesToBeBound array
Note: I have replaced actual package names with *.
I'm surprised it works on a bounce... all of your JAXB bits need to line up, you should be using the moxy jaxb provider at all times. If it's failing after initial deploy, then working after a bounce, I suspect that you want to specify the moxy jaxb provider in your system properties ( -Djavax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory ) and ensure that they're available to jboss when your app is not deployed.

Jackson (jersey) deserialize exception - (for id type 'Id.class'): no such class found

I have a REST web application based on Jersey and running in an OSGi container - Geronimo3. The service is returning results fine with Json POST data and able to marshal json output to java object. I have written a REST client and that too works fine with main method getting back the response object.
However, Rest client fails in one scenario - when called from Bundle Activator class in a OSGi web application. It gives below error in this case.
Also when the web application is fully initialized, the Rest client works fine in request scope. I am suspecting some issue with classloaders since OSGi classloading is different regular webapps (tomcat). Also the response class uses #JsonTypeInfo annotation to map Interface type to concrete class.
Caused by: java.lang.IllegalArgumentException: Invalid type id 'com.nnn.IContentValue$ContentText' (for id type 'Id.class'): no such class found
at org.codehaus.jackson.map.jsontype.impl.ClassNameIdResolver.typeFromId(ClassNameIdResolver.java:57)
at org.codehaus.jackson.map.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:113)
at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:82)
at org.codehaus.jackson.map.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:52)
at org.codehaus.jackson.map.deser.std.MapDeserializer._readAndBind(MapDeserializer.java:321)
at org.codehaus.jackson.map.deser.std.MapDeserializer.deserialize(MapDeserializer.java:249)
at org.codehaus.jackson.map.deser.std.MapDeserializer.deserialize(MapDeserializer.java:33)
at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:299)
at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:414)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:697)
I found a workaround that I'm documenting.
It is caused due to org.codehaus.jackson.map.util.ClassUtil.findClass loading typeid class from org.eclipse.core.runtime.internal.adaptor.ContextFinder that is different from OSGi bundle classloader during bundle init phase.
I replaced the contextClassLoader using Thread.currentThread().setContextClassLoader(getClass().getClassLoader()) before making the jersey client call and reverting it to original one in finally block.

com.db4o.internal.query.ObjectSetFacade' was not included

GWT + Springs + DB4o: Any idea how to make this work without adding a new RPC class
[WARN] Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type 'com.db4o.internal.query.ObjectSetFacade' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = [com.ppp.prm.portal.shared.dto.MComments#2214ab5, com.ppp.prm.portal.shared.dto.MComments#4fda105f, com.ppp.prm.portal.shared.dto.MComments#7568f5ed, com.ppp.prm.portal.shared.dto.MComments#3de9d6d3, com.ppp.prm.portal.shared.dto.MComments#4316d666, com.ppp.prm.portal.shared.dto.MComments#1055e4f3, com.ppp.prm.portal.shared.dto.MComments#772a15e5, com.ppp.prm.portal.shared.dto.MComments#6c03aa81]
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:619)
at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:153)
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:539)
at com.google.gwt.user.server.rpc.RPC.encodeResponse(RPC.java:616)
Issue
RPC 101 - Objects need to implement IsSerializable or Serializable interface. None of the classes ObjectSetFacade or its super class implement them. Reference more rules - https://developers.google.com/web-toolkit/doc/latest/tutorial/clientserver
DB4o is non gwt java library. You cannot send com.db4o.internal.query.ObjectSetFacade in any RPC call.
Solution
1) You should convert from db40 objects to domain objects/pojos compatible with GWT and RPC.
2) Example - we convert Hibernate objects to Domain pojos using Dozer on server. https://developers.google.com/web-toolkit/articles/using_gwt_with_hibernate

how can I use an interface entity in RequestFactory's client-side?

I have some service methods which return entities that are not implemented yet.
For example, I have an interface called IUser and some classes that implemented this interface such as GuestUser and AdminUser.
All entity classes are well-defined already and I want to use their jar files without manipulating them.
My problem is when I wanted to define ProxyFor IUser.class in client-side entity and to call service methods that their return type are IUser. While calling these methods I get the following error: The domain type com.bis.entity.security.GuestUser cannot be sent to the client.
Is there any way to call methods that deal with interfaces in RequestFactory or do I have to change all the service methods to utilize class entitis?
You have to use classes for now. See http://code.google.com/p/google-web-toolkit/issues/detail?id=5762

Hibernate, Gilead and GWT

I'm experiencing some problems with GWT and Gilead/Hibernate
I did my code according to the tutorial but it fails with
com.google.gwt.user.client.rpc.SerializationException: Type 'ru.atamur.entity.UserEntity_gilead_15' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = ru.atamur.entity.UserEntity_gilead_15#133fa82
Looking at the source code I can see that Gilead transformed my UserEntity into UserEntity_gilead_15 inside GileadRPCHelper.parseReturnValue(returnValue, _beanManager)
I can see that this was deliberately done by ProxyClassMapper (I'm trying to use proxy mode), so I was wondering where Gilead was expecting to tell GWT Serilization mechanism about this new proxy class it introduced ...
Can you share your code ?
before that I want to say that SerializationException is thrown when your class doesn't implement isSerializable interface that you send it to the server.
Every class that you send to the server should implement isSerializable interface