Monday, November 21, 2011

Solving __OAUX_GENXSD_.TOP.XSD with BPEL

When you use an external web service in combination with a BPEL service component in an Oracle SOA Suite 11g composite and you follow this great AIA blog about Best Practices for Decoupling Services and Avoiding Invalid Composites at Server Startup then you can get this __OAUX_GENXSD_.TOP.XSD error in

  • JDeveloper, when you build the composite.
  • On the SOA Suite when the service is invoked for the second time, probably on your test or acceptance environment. 
Before we start with the possible fixes, first why do you get this error. 

You can only get this error when you use BPEL in your composite. With the mediator service component I don't get this error.

In my test composite I have a simple OSB proxy and use this as a reference. So I provide the WSDL url to the WS adapter and enabled the option to download the WSDL to your project.   


Because I don't want any deployment problems ( invalid composites at deployment time or at a soa server reboot when the OSB proxy is down ). I downloaded the XSDs of the WSDL, fixed the WSDL imports. Now we can put the WSDL and the XSDs in our project folder or add them to a central place like the MDS. 

When we take a look at the reference part in the composite.xml you will see the following.
The endpoint is loaded from the Customer.wsdl ( location attribute of the binding.ws element ) and uses the port attribute to find the endpoint in the Customer.wsdl.


Here is the wsdl with the endpoint.


This works great in development ( cause you don't need to change anything)  but when you have to deploy to test or acceptance you will generate a config plan where you override the location attribute of the binding.ws (reference) with the Test OSB Proxy WSDL url, so it will use that endpoint for test or acceptance.

On the SOA Suite you can invoke this service once and after that you can get this __OAUX_GENXSD_.TOP.XSD error. Somehow the second time the SOA Suite will retrieve the test OSB Proxy WSDL and it's XSDs from the cache and it compares it with the local XSDs of your project or MDS. When there is a difference in one of the XSDs you will get this error ( can be something minor like an element annotation ). 
    
This can also happen in the JDeveloper SOA Composite builder when you load the same XSDs local and remote. 


So the solution is to keep the XML schemas in sync ( remote and local ) but this is almost impossible or you need to build everything with Maven or ANT and always replace the XSDs in every project. This also requires a lot of unit testing.

Even then you probably don't have much influence on remote services. 

So the best solution is to avoid the loading of remote WSDL. You only need to update the endpoint for the Test or acceptance environment, not to load the whole WSDL. So don't try to replace the location attribute of the binding.ws element in the composite.xml but try to update the endpoint in the WSDL located in your project or in the MDS.   

And if you use contract first Java (EJB) Web Services in Oracle Suite then you should always use the WSDL and the XSDs in your Java Web Services else you will get different schema imports then the original WSDL & XSDs.

I tested this with the Patch Set 3 version of SOA Suite 11g. 

Tuesday, November 8, 2011

Changing a navigation model on a page in WebCenter

WebCenter has a default navigation model (menu) which is located in the navigations folder and is defined as portal preference in the adf-config.xml file. But this menu is used in every page of the portal. I want to change this, so when you are not authenticated you will see the normal website links. But when you go to the internal page the menu will be switched to the application navigation model.
Special thanks for Maiko Rocha of the WebCenter A-Team for helping me solving this requirement.

First I create a new jspx page based on the global template called Internal.jspx and add a navigation reference to this page in the default-navigation-model.xml.


Now we can create a navigation model which will be used in the internal page. This menu has a link to the home page so the user can go back to the default menu.



Open the global template called pageTemplate_globe.jspx and go the menu part.  Here we will change the default navigation model.

from
#{navigationContext.defaultNavigationModel.listModel['startNode=/, includeStartNode=false']}

to
#{navigationContext.navigationModel[ menuSwitcher.menu ]                                  .listModel['startNode=/, includeStartNode=false']}

Where menuSwitcher is a request bean.

To determine what navigation model I need to use I will check the current page and return the right navigation reference.


The request bean



You can also use EL instead of a request bean.


<af:forEach var="node" varStatus="vs"
   items="#{navigationContext.navigationModel[ 
          controllerContext.currentViewPort.viewId eq '/oracle/webcenter/portalapp/pages/Internal.jspx' ? 
             '/oracle/webcenter/portalapp/navigations/navigationModelInternal.xml'  : 
             '/oracle/webcenter/portalapp/navigations/default-navigation-model.xml' 
   ].listModel['startNode=/, includeStartNode=false']}">


Here some pictures of the home page

After being authenticated, some extra menu links appears


And at last, the internal page with the new navigation model.