Thursday Oct 24, 2013

JAXB Errors and Best Practices when Generating WebService Proxies for Oracle Sales Cloud (Fusion CRM)

I've recently been building a REST Service wrapper for Oracle Sales Cloud and initially all was going well, however as soon as I added all of my Web Service proxies I started to get weird errors.. 

My project structure looks like this


What I found out was if I only had the InteractionsService & OpportunityService WebService Proxies then all worked ok, but as soon as I added the LocationsService Proxy, I would start to see strange JAXB errors.

Example of the error message

Exception in thread "main" javax.xml.ws.WebServiceException: Unable to create JAXBContext
at com.sun.xml.ws.model.AbstractSEIModelImpl.createJAXBContext(AbstractSEIModelImpl.java:164)
at com.sun.xml.ws.model.AbstractSEIModelImpl.postProcess(AbstractSEIModelImpl.java:94)
at com.sun.xml.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:281)
at com.sun.xml.ws.client.WSServiceDelegate.buildRuntimeModel(WSServiceDelegate.java:762)
at weblogic.wsee.jaxws.spi.WLSProvider$ServiceDelegate.buildRuntimeModel(WLSProvider.java:982)
at com.sun.xml.ws.client.WSServiceDelegate.createSEIPortInfo(WSServiceDelegate.java:746)
at com.sun.xml.ws.client.WSServiceDelegate.addSEI(WSServiceDelegate.java:737)
at com.sun.xml.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:361)
at weblogic.wsee.jaxws.spi.WLSProvider$ServiceDelegate.internalGetPort(WLSProvider.java:934)
at weblogic.wsee.jaxws.spi.WLSProvider$ServiceDelegate$PortClientInstanceFactory.createClientInstance(WLSProvider.java:1039)
......

Looking further down I see the error message is related to JAXB not being able to find an objectFactory for one of its types

Caused by: java.security.PrivilegedActionException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 6 counts of IllegalAnnotationExceptions
There's no ObjectFactory with an @XmlElementDecl for the element {http://xmlns.oracle.com/apps/crmCommon/activities/activitiesService/}AssigneeRsrcOrgId
this problem is related to the following location:
at protected javax.xml.bind.JAXBElement com.oracle.xmlns.apps.crmcommon.activities.activitiesservice.ActivityAssignee.assigneeRsrcOrgId at com.oracle.xmlns.apps.crmcommon.activities.activitiesservice.ActivityAssignee

This is very strange... My first thoughts are that when I generated the WebService Proxy I entered the package name as "oracle.demo.pts.fusionproxy.servicename" and left the generated types as blank. This way all the generated types get put into the same package hierarchy and when deployed they get merged...



Sounds resaonable and appears to work but not in this case.. 

To resolve this I regenerate the proxy but this time setting :

Package name : To the name of my package eg. oracle.demo.pts.fusionproxy.interactions
Root Package for Generated Types :  Package where the types will be generated to, e.g. oracle.demo.pts.fusionproxy.SalesParty.types


When I ran the application now, it all works , awesome eh????

Alas no, there is a serious side effect.

The problem now is that to help coding I've created a collection of helper classes , these helper classes take parameters which use some of the "generic" datatypes, like FindCriteria.

e.g. This wont work any more

public static FindCriteria createCustomFindCriteria(FindCriteria pFc,String pAttributes)

Here lies a gremlin of a problem.. I cant use this method anymore, this is because the FindCriteria datatype is now being defined two, or more times, in the generated code for my project. If you leave the Root Package for types blank it will get generated to com.oracle.xmlns, and if you populate it then it gets generated to your custom package.. The two datatypes look the same, sound the same (and if this were a duck would sound the same), but THEY ARE NOT THE SAME...

Speaking to development, they recommend you should not be entering anything in the Root Packages section, so the mystery thickens why does it work..

Well after spending sometime with some colleagues of mine in development we've identified the issue.. Alas different parts of Oracle Fusion Development have multiple schemas with the same namespace, when the WebService generator generates its classes its not seeing the other schemas properly and not generating the Object Factories correctly... 

Thankfully I've found a workaround

Solution Overview

  • When generating the proxies leave the Root Package for Generated Types BLANK
  • When you have finished generating your proxies, use the JAXB tool XJC and generate Java classes for all datatypes 
  • Create a project within your JDeveloper11g workspace and import the java classes into this project
  • Final bit.. within the project dependencies ensure that the JAXB/XJC generated classes are "FIRST" in the classpath

Solution Details

  • Generate the WebServices SOAP proxies
    • When generating the proxies your generation dialog should look like this

    • Ensure the "unwrap" parameters is selected, if it isn't then that's ok, it simply means when issuing a "get" you need to extract out the Element
  • Generate the JAXB Classes using XJC
    • XJC provides a command line switch called -wsdl, this (although is experimental/beta) , accepts a HTTP WSDL and will generate the relevant classes. You can put these into a single batch/shell script
    • xjc -wsdl https://fusionservername:443/appCmmnCompInteractions/InteractionService?wsdl
      xjc -wsdl https://fusionservername443/opptyMgmtOpportunities/OpportunityService?wsdl

  • Create Project in JDeveloper to store the XJC "generated" JAXB classes
    • Within the project folder create a filesystem folder called "src" and copy the generated files into this folder. JDeveloper11g should then see the classes and display them, if it doesnt try clicking the "refresh" button

  • In your main project ensure that the JDeveloper XJC project is selected as a dependancy and IMPORTANT make sure it is at the top of the list. This ensures that the classes are at the front of the classpath

And voilĂ ..

  • Hopefully you wont see any JAXB generation errors and you can use common datatypes interchangeably in your project, (e.g. FindCriteria etc)


About

Architect & Technology Evangelist - If its middleware I'm interested

Search

Archives
« October 2013 »
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
25
26
27
28
29
30
31
  
       
Today