Pages

Showing posts with label jdeveloper 11g soa suite. Show all posts
Showing posts with label jdeveloper 11g soa suite. Show all posts

Tuesday, June 11, 2013

Custom OSB Reporting Provider

With the OSB Report Action we can add some tracing and logging to an OSB Proxy, this works OK especially when you add some Report keys for single Proxy projects but when you have projects with many Proxies who are invoking other JMS or Local Proxies than the default reporting tables (WLI_QS_REPORT_DATA, WLI_QS_REPORT_ATTRIBUTE ) in the SOA Suite soainfra schema is not so handy.
I want to introduce a conversation id which will be used in all the Proxies and a unique message id for a proxy which will be used in the request and response. Plus it has a status field for the whole conversation ( default = OK, when there is an error somewhere in the conversation then the status will be ERROR)

With this as result. 2 conversations 1 is OK and all matching detail messages ( every proxy has its own messageId so you know which request, response or error belong to each other )
This way I can build my own application which can display all this data, combine this for example with my ErrorHospital data.





The default JMS Reporting part works great for me, so in my Custom Reporting provider I want to re-use the publishing way of the OSB ReportMessage ObjectMessages in the JMS Queue ( wli.reporting.jmsprovider.queue )

So in the next steps I will create a new EJB Application with a Message Driven Bean who reads this ObjectMessage and pass it on to an EJB Session Bean which will use JPA to persist the data in these two tables.

So the first step is to create a new application in JDeveloper and this listener class to the weblogic-application.xml ( located in the src/meta-inf folder of your workspace )
<listener-class>
com.bea.wli.reporting.jmsprovider.init.JmsReportingStartupAndShutdown
</listener-class>

This will enable the OSB Reporting.

You also need plus you need to untarget the default JMS reporing Provider else both applications tries to read the JMS messages.




Add the following jars to your application and uncheck the Export selection ( they are already there on the osb server ). You can find the com.bea.alsb.reporting.api.jar and com.bea.alsb.reporting.impl.jar in your Oracle_OSB1/lib/modules folder of your middleware home



Create a Message Driven Bean


Next step is to tune this MDB so it runs under the ALSBSystem role (ejb-jar.xml ) and in the weblogic-ejb-jar deployment descriptor I set the max and initial pool to 1, this way I can make sure that I have only 1 message record per conversation Id plus this MDB runs as alsb-system-user user.

Add our two JPA entities ( message and message detail ) to the model project and create an EJB session bean with a local interface. This EJB will be invoked by the MDB and pass on the ReportMessage entity.
In the persistence.xml I will reuse the already created wlsbjmsrpDataSource Datasource  ( the message table are also in the soainfra schema )

The EJB session bean does all the heavy work, it needs to determine if the conversation record already exists and retrieve all the Report Action Keys ( message labels).  

Click here to see the EJB Session bean https://github.com/biemond/osb11g_examples/blob/master/CustomOSBReporting/JmsReporting/Model/src/nl/amis/mw/reporting/services/OSBReportingSessionEJBBean.java

Last steps is to make on the project level an EJB deployment ( ejb jar ) and add this to Application deployment profile ( ear ), uncheck the export of all the reporting jars and deploy this to the OSB Server ( must deploy from application menu else the listener class is not loaded )

The last step is to add the report action to all our OSB Proxies

We also need a header element in our message body or header where we can store the conversationId and pass on the other Proxies so every report action can use these values as keys.
In every proxy I first need to add the internal OSB proxy messageID to a variable ( and do not pass it on )  I will do this in the first assign.


This way I can use it in the Request and Response Report Action ( So I know which request ,response or error belong to each other).


In the first Report action I also provided some extra data ( like messagetype, sender, receiver)  this will also be stored in the message table.


In the other proxies I only need to use the Conversation Id and the messageId of that proxy.


In the Error handler I also added a report action so I know what the error is and set the status of the message to ERROR



That's all for the custom reporting part. Off course you can add extra field to these tables by adding your own report keys. You only need to change the EJB and the JPA Entities.

Here you can find all the code together with an OSB demo workspace.
https://github.com/biemond/osb11g_examples/tree/master/CustomOSBReporting


   

Tuesday, April 2, 2013

Token Configurations in Oracle SOA Suite PS6 ( 11.1.1.7.0)

Oracle Soa Suite PatchSet 6 or 11.1.1.7.0  now has support for Token configurations which really can help administrators in configuring or overriding external Web Service Reference parameters like the protocol ( http, oramds or https ),  the remote host etc. And more important if you do it right you can kick out the all those Soa Suite deployment plans :-)

Important to know this only works on the location attribute of the binding.ws element of the composite.xml file. But when you use Metadata Service (MDS) and call a Web Service like a Java WS, .Net WS,  OSB or SOA Suite Reference Services then you can use this new feature.

In this blogpost I will show you all the steps.

First step is to make all these services in depended of each other ( Don't want invalid composites or want to use deployment plans ), I followed this great AIA blog about Best Practices for Decoupling Services and Avoiding Invalid Composites at Server Startup

In this demo I created a workspace with a MDS project which contains some WSDL's with a XML Schema. This WSDL is used in the Helloworld Reference Soa project. Deployed it together with the MDS soa sar and I put the Impl of the Reference WSDL back to the MDS so it can be used in my other main project ( I downloaded it from the EM and changed the xml schema import ).

The main project will call this helloworld reference service and in this project we will use a server name token in the WSDL url ( location attribute of the binding.ws element ).


In my main project I added this externel reference web service to my composite by selecting the Reference Impl from the MDS  ( First add a File MDS in the Resource Palette and map this to your local MDS location and finally lookup the WSDL, for compiling you also need to add an extra MDS location to the adf-config.xml )

After adding the reference service, we need to fix some hard references in the composite.xml to this remote service.
  • Change the location attribute of the composite import to oramds://
  • Do the same for ui:wsdlLocation attribute of the Reference element.
  • In the location attribute of the Binding.WS element we need to use the real reference WSDL url ( see the EM for the reference WSDL url  ). 



Do the same for the Reference Wrapper WSDL



Now our main Soa Suite project only needs this reference service at runtime and we won't have any deployment issues or invalid composites after a reboot of the Soa Suite Service.

Next step is to create a Token file which contains some server host entries, we can use this file in the JDeveloper Token wizard or later when we want to import these Tokens in the Oracle Enterprise Manager.  See this url for an Token xml example http://docs.oracle.com/cd/E28280_01/dev.1111/e10224/sca_bindingcomps.htm#CIHFJFJC

I added two host key values entries 


Click the token button of the composite.xml editor.


Select our reference service and click on edit.

Lookup the just created Token file and on the Host field we can lookup our LocalSoaServer entry.




This will change the location attribute to http://${LocalSoaServer}:8001.....


We are ready to compile the project.


The Soa Suite server does not know this LocalSoaServer token so we need to create this token in the Enterprise Manager.

Go to SOA Infrastructure -> SOA Administration -> Token Configurations.


Click on Modify Configuration File and add a new token.



Add the LocalSoaServer Token with its value.


Commit this token.



 This will update the mdm-url-resolver.xml file located in the config/fmwconfig folder of the weblogic soa domain.


 We can also upload the Token file of JDeveloper, this will add the missing tokens.



You need to reboot the Soa Server, after this you can deploy the main project and test the main project.

here is the demo workspace with all the above code.

Thursday, August 9, 2012

Generating an EJB SDO Service Interface for Oracle SOA Suite

In Oracle SOA Suite you can use the EJB adapter as a reference or service in your composite applications. The EJB adapter has a flexible binding integration, there are 3 ways for integrating the remote interface with your composite.

First you have the java interface way which I described here this follows the JAX-WS way. It means you need to use Calendar for your Java date types and leads to one big WSDL when you add a wire to a service component.

Second way is EclipseLink Moxy this solution is great when you can't change your java interfaces. Antony Reynolds made a great blogpost how to use EclipseLink moxy in Oracle Soa Suite.

The last way is generating a Service Data Object (SDO) service interface on your EJB Session Bean, This leads to a WSDL with a operation XSD and entity XSDs which can be used / read by the EJB Adapter ( no one big WSDL ).  Use the java data types you want to use, JDeveloper can re-generate the SDO interface and no need to drag a dummy wire to refresh the EJB WSDL when you change the EJB Session bean.

In 2009 I already described this SDO feature but now with Patch Set 5 this SDO feature is finally working well. Before PS5 it was really hopeless.

So let's explain how this works in PS5. I already made a simple HR JPA Model project with a EJB Session Bean.


Before we start we need to think about lazy and eager object loading. In this Department entity I will eager retrieve the manager and employees of this department.


In the Employee entity I will use the Lazy fetch type on the department attribute.


Just like the java interface mapping way we can't have circular references between department and employees XSD.  We need to break the loop so add @XmlTransient to the getter of the department attribute of the employee entity.  ( now the department element will be skipped in the employee XSD )


Select your EJB Session Bean ( Right Click ) and select Create Service Interface.


When we want to use this SDO interface in Oracle SOA Suite we need to enable the Configure as an ADF-BC Service. This will add the necessary SDO annotations on the Remote Interface.



With this as result


The generated Department entity XSD.


The EJB SDO Session Bean WDSL

JDeveloper adds PortableWebService annotation to the EJB Session bean.


The remote interface with all the web annotations on a SDO method.



Also when you want the same behaviour as a Database adapter you can force to start a new transaction and not take part in the BPEL transaction. This way you can see if the transaction is successful at the end of the invoke instead of the end of BPEL.


JDeveloper also adds code to the EJB Session Bean to marshall and unmarshall the java or xml.


Think about which attributes can be empty else you will get some null pointer exceptions.


Also it will load all the SDO XSDs in the EJB Session Bean. If you don't have circular XSD references  then loading should be successful.


In a java client we can test the SDO interface ( this will not use the remote interface annotations) by first loading the XSDs and invoking a SDO session bean method. Loading of the XSDs is necessary else   you will get some EclipseLink objects instead of the department of employee objects.


Deploy the EJB to the SOA Suite Server and also generate an interface jar which does not contain the meta-inf folder  and the Bean.

Now is the time to configure the EJB adapter in Oracle SOA Suite. Drag the EJB Adapter to the reference side of the composite.

Lookup the jar and the WSDL. The wizard will copy the interface jar and WSDL, XSDs to your project.


Fix the jndiName bug in the reference service, go to source mode of the composite.xml , rename the uri attribute to jndiName.



Finish your composite and deploy it. When you go for a test drive you will see something like this.


Here you can download my example project.
https://github.com/biemond/soa11g_examples/tree/master/SoaEjbSdoReference


Thursday, August 2, 2012

Return a fault from an Asynchronous Web Service

In an asynchronous web service we can't return a soap fault like a synchronous service but that does not mean you can't report back the fault to the calling asynchronous process.

basically you got three options.

  • Off course handle the fault in the error hospital and give back the response. 
  • In the response message you can add a section ( a XSD choice with success and fault section) which can be used for faults.
  • Do a callback to a common fault operation of the calling process. This can be a JMS message with the messageId/correlationId or a Web Service invocation where we use the correlation of BPEL to match the fault message with the right process. 

In this blogpost I will show how to implement the last two options in Oracle BPEL.

First we start with returning the fault in a response message.

For this I added a status element to the response and a choice for a success and a fault .


In the catch section you can also invoke the callback response and in the Assign activity you can fill the fault section of the response message.




Do a fault callback to the calling process,  for this we need to do the following.

Create an Asynchronous BPEL process.

Define a fault response schema. The EmployeeId element is necessary, we need this for the correlation of the BPEL processes.


Then make a new WSDL with the fault callback operation and add a fake endpoint. ( we will override this endpoint from BPEL, because we don't know the endpoint of the calling process).


Add a FaultCallback reference web service based on this WSDL and add a wire to the BPEL process.


In the BPEL receive activity, we need to capture the fault callback url. We can optional use this for the fault response endpoint.  Go the properties tab and capture the value of the faultToAddress property. Put the value in the faultCallBackUrl variable.



In the Catch section of the BPEL process we can invoke the fault reference service. Off course use an assign to add the EmployeeId and provide a fault message.


Open the fault invoke activity and go to the properties tab.


We need to set the endpointURI property with the faultCallBackUrl variable value.


That is all for the Asynchronous Service.

Next step is to use this Asynchronous Fault Service in an other asynchronous BPEL process.

We need to make a WSDL ( contract first ) with a portType which also contains the fault operation, this must match with the reference WSDL of the Asynchronous Fault Process. So operationName, Message and namespace must match.

Create a new BPEL process which is based on this WSDL ( expose this BPEL as a service ) and also add wire the Asynchronous Fault process.


This is the process with InvokeEmployee activity which calls the Asynchronous Service.



Open this invoke activity and go to the properties tab where we set the faultToAddress property. This is the endpoint of this BPEL process and will be used for the fault callback.


After the invoke we need to use a pick activity and add an extra onMessage to the pick activity.
First OnMessage will be used for the normal callback situation.


The second will be used for the fault Response.


The last step is to setup correlation in this BPEL for the returning fault message.

on the receive add a correlation set and initiate this ( I got a NPE when I tried to set it on the invoke ). The Set is based on the employeeId element.



Add two Property Aliases , first is based on the employeeId element of the Fault Message and second is the employeeId of the request message.


On the fault OnMessage we need to add the same correlation set and this time we don't need to initiate it.



If everything is Ok we will see the following in the Enterprise Manager.

on the invoke we set the faultToAddress, the normal response OnMessage is cancelled and the fault OnMessage gets a response with the fault message.



On github you can download this example https://github.com/biemond/soa11g_examples/tree/master/AsynchronousFaultHandling