Hello experts,
I am currently developing a Bluemix application using a RESTful interface (jaxrs-2.0). The service is working as expected in general.
Passing simple Objects seems to work without any issues. However, I would like to use the Joda library for Date, DateTimes and Calendar functions. There is one complex object - ClassA
- that should be send from the client to update. ClassA
contains 2 DateTime
objects of the Joda library.
I have already written the XMLJavaAdapterTyp
and it is set on package level. So passing objects back from the server works just fine. The server is consuming and producing application/json
& application/xml
content types.
The objects are stored in a different package than the RESTService interface. A summary of the project structure can be found below:
src
|--packageA
| |--ClassA.java
| | |--DateTime start
| | |--DateTime end
| | |-- ... other ('simple') fields ...
| |
| |--XMLJavaAdapter implementation for Joda DateTime
| |
| +--package-info
| +--XMLJavaApater Annotation
|
|--packageB
+--RESTService
|--...several methods
+--@PUT public ClassA update(ClassA instanceToUpdate)
I am deploying the project to a local WAS Liberty profile, containing following features:
<featureManager>
<feature>jpa-2.1</feature>
<feature>localConnector-1.0</feature>
<feature>jaxrs-2.0</feature>
</featureManager>
The server start shows additionally following message:
[AUDIT ] CWWKF0012I: The server installed the following features: [jdbc-4.1, localConnector-1.0, json-1.0, jaxrs-2.0, jpa-2.1, servlet-3.1, jaxrsClient-2.0, jndi-1.0].
I already tested some GET methods returning ClassA
and this is working fine. However, while trying the update method (@PUT) via a RESTConsole, I am receiving the following issue in the console:
[ERROR ] SRVE0777E: Exception thrown by application class 'org.codehaus.jackson.map.ext.JodaDeserializers.provide:32'
java.lang.NoClassDefFoundError: org/joda/time/ReadableInstant
at org.codehaus.jackson.map.ext.JodaDeserializers.provide(JodaDeserializers.java:32)
at [internal classes]
Caused by: java.lang.ClassNotFoundException: org.joda.time.ReadableInstant cannot be found by com.ibm.ws.jaxrs-2.0.common_1.0.10.cl50720150827-0437
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:439)
... 1 more
Some researches in the net showed additional information that this seems to be caused by a missing resource export: java.lang.ClassNotFoundException org.joda.time.ReadableInstant not found by jackson-mapper-asl There also seems to be a fix: Classloading / module issue with using resteasy-jackson-provider and joda classes
I have added the Joda Library (jar-file) as Library in the Java Built Path (as Library) and marked it also as Export to be sure. Moreover the jar-file is included in the WebContent/WEB-INF/lib/
directory.
Unfortunately, I do not know, where to apply the fix mentioned in the above reference. I am suspecting the WAS Liberty is missing the required reference, as the console stack trace shows com.ibm.ws.jaxrs-2.0.common_1.0.10.cl50720150827-0437
cannot find the required class. Any hint is much appreciated!
I attached the whole WAS Liberty messages.log (it is not that long) to the question so you see the full stack as well.
Does anybody know how to resolve such an issue? I already spent several hours with but I am not close to a solution I am thinking.
Thanks a lot for your inputs!
Best Regards
Steffen
Already adjusted the server.xml configuration as follows:
<library id="joda" apiTypeVisibility="spec,ibm-api,api,third-party">
<fileset dir="${server.config.dir}/lib/joda" includes="*.jar" scanInterval="0s"/>
</library>
<library id="jackson" apiTypeVisibility="spec,ibm-api,api,third-party">
<fileset dir="${server.config.dir}/lib/jackson" includes="*.jar" scanInterval="0s"/>
</library>
...
<webApplication id="WebApp" location="WebApp.war" name="WebApp">
<classloader delegation="parentFirst" privateLibraryRef="joda"></classloader>
<classloader delegation="parentLast" privateLibraryRef="jackson"></classloader>
</webApplication>
The ${server.config.dir}/lib/joda
directory contains the Joda library. The ${server.config.dir}/lib/jackson
includes the jackson-core-asl
& jackson-mapper-asl
(both in version 1.9.13).
Additional recommendations are highly appreciated!
Adding the jackson libraries to the WebContent/WEB-INF/lib
as well, causes following exception:
org.codehaus.jackson.map.ext.JodaDeserializers cannot be cast to org.codehaus.jackson.map.util.Provider
Moreover, the previously working GET mehtod to receive a ClassA
object is throwing following error:
java.lang.ClassCastException: org.codehaus.jackson.map.ext.JodaSerializers cannot be cast to org.codehaus.jackson.map.util.Provider
Summarizing it looks like the WAS Liberty profile is not working in harmony with the jackson libraries in combination with Joda
I am not whether this is counted as progress in solving the issue.
Additional hints are still much appreciated!
Answer by S.Baumann (2871) | Oct 18, 2015 at 10:34 AM
Hello all,
I finally solved the issue by using everything @Tom has provided as well as using the correct jackson library. Mistakenly, I was focused on jackson-core-asl
& jackson-mapper-asl
only based on the fix for JBoss cited in my questions.
After using a 'full' jackson library, the issue is gone and I am able to share the required objects. Moreover, the full library seems to be on a later release as well, which is somehow even better.
Please find below the whole working configuration that is working now:
${server.config.dir}
|--lib
| |--json
| | +--joda-time-2.8.2.jar
| |
| +--jackson
| +--jackson-all-1.9.9.jar
|
+--... default directories
<library id="joda" apiTypeVisibility="spec,ibm-api,api,third-party">
<fileset dir="${server.config.dir}/lib/joda" includes="*.jar" scanInterval="0s"/>
</library>
<library id="jackson" apiTypeVisibility="spec,ibm-api,api,third-party">
<fileset dir="${server.config.dir}/lib/jackson" includes="*.jar" scanInterval="0s"/>
</library>
...
<webApplication id="WebApp" location="WebApp.war" name="WebApp">
<classloader delegation="parentFirst" privateLibraryRef="joda"></classloader>
<classloader delegation="parentLast" privateLibraryRef="jackson"></classloader>
</webApplication>
WebContent
|--WEB-INF
| |--lib
| | |--jackson-all-1.9.9.jar
| | +--joda-time-2.8.2.jar
| |
| +--... default stuff like web.xml
|
+--META-INF (default)
src
|--packageA
| |--ClassA.java - annotated with @XmlRootElement
| | |--DateTime start
| | |--DateTime end
| | +-- ... other ('simple') fields ...
| |
| |--XMLJavaAdapter implementation for Joda DateTime
| |
| +--package-info
| +--XMLJavaApater annotation
|
|--packageB
+--RESTService (consumes & produces JSON and XML)
|--...several methods
|--@GET public ClassA get(String id)
+--@PUT public ClassA update(ClassA instanceToUpdate)
Many thanks to @Tom for his excellent information to the classloader settings and API usage in WAS Liberty! Hope this helps others, too.
Best regards
Steffen
Answer by Tom Alcott (1727) | Oct 17, 2015 at 03:05 PM
The fix and resolution cited are specific to JBoss and the JBoss module.xml file (which is specific to the JBoss server implementation)
The Liberty profile analog steps are detailed here
An additional suggested reference is
Hello @Tom
thanks for your response. Some additional searches lead me to the same direction. However, I was not sure how to set it properly. Thanks for your reference, showing a great example. Unfortunately, it did not show any change.
The configuration looks as followed:
<webApplication id="MyApp" location="MyApp.war" name="MyApp">
<classloader delegation="parentLast">
<privateLibrary>
<fileset dir="${server.config.dir}/lib" includes="*.jar" scanInterval="5s" />
</privateLibrary>
</classloader>
</webApplication>
The ${server.config.dir}/lib
contains the same libraries as the built path does.
However, I tried to 'override' the Jackson library to use the latest one. This forced the application to throw a different exception. Key message is as follows:
org.codehaus.jackson.map.ext.JodaDeserializers cannot be cast to org.codehaus.jackson.map.util.Provider
I got the error when I added the jackson libraries (jackson-core-asl & jackson-mapper-asl) to the WebContent/WEB-INF/lib
directory
I also added the jackson libraries to the created ${server.config.dir}/lib
directory - no change. Not sure whether this is progress. Do you maybe have any other idea to solve this issue?
Meanwhile I have reviewed the source code of the mentioned jackson classes org.codehaus.jackson.map.ext.JodaDeserializers
and org.codehaus.jackson.map.util.Provider
. As the JodaDeserializers
is implementing the Provider
interface there is not explanation to me, why there should be a ClassCastException
.
GrepCode of JodaDeserializers shows the following:
...
14 import org.codehaus.jackson.map.util.Provider;
...
22 public class JodaDeserializers
23 implements Provider<StdDeserializer<?>>
24 {
...
Using the maven cloudfoundry plugin how can I import trusted certificates? 0 Answers
Why WEB-INF\lib\*jar become a file after cf push to bluemix? 3 Answers
Oracle DB Service Plugin for Liberty Buildpack 1 Answer
Where to find Liberty features like couchdb-1.0 etc., and how to add those into my Eclipse 2 Answers
Connecting to Dashdb using a data source in the Liberty For Java Profile in Bluemix 2 Answers