Best Practices Generating WebService Proxies for Oracle Sales Cloud (Fusion CRM)
- by asantaga
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 JAXBContextat
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
IllegalAnnotationExceptionsThere's no ObjectFactory with an @XmlElementDecl for the
element
{http://xmlns.oracle.com/apps/crmCommon/activities/activitiesService/}AssigneeRsrcOrgIdthis 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.interactionsRoot 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?wsdlxjc -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)