Ever wondered why a SOA composite goes to invalid state when the SOA server starts up? No matter what you try - restarting the composite from within the fusion middleware control (EM console) or undeploying - nothing would work. Only a server restart "Might" rid you of the issue.
I am carefully using "Might" here because, the SOA composite under consideration might refer to a service which could be down when the composite was started. This happens because;
The SOA server doesn't know of the service dependencies that a SOA composite has.
For instance let us consider a SOA composite A referencing external services B, C & D deployed on the same server instance. Ideally, we would like to have a service startup order where the services B, C & D are started ahead of composite A.
But that is not the reality as there is no way to set the service startup priority on the SOA server. It wouldn't be a nice idea to weave this setting at the server level as well because, consider a cyclic dependency issue where composite A references composite B and vice versa which would be too complex & cause instability.
This is a classic case for any SOA environment and the issue here is because the concrete WSDL references are used in the SOA composite to connect with the external services.
Now the question is how do we resolve these service dependency issues?
Answer lies in leveraging the SOA infrastructure capability. If you look closely into any SOA composite (source code), there will be a set of common services that will be referenced from the metadata store (MDS);
<import namespace="http://xmlns.oracle.com/bpel/workflow/taskService"
location="oramds:/soa/shared/workflow/TaskServiceInterface.wsdl"
importType="wsdl"/>
These service definitions are stored in the MDS repository which is available all the time for the SOA services to reference provided the underlying DB is up & running. You can check this for yourself by establishing a SOA MDS repository connection from the JDeveloper resource palette.
Similarly, as a best practice you can store all the abstract WSDL definitions of the referenced services in the MDS repository & reference them in your SOA composite. This way whenever the server tries to start the services, irrespective of the service startup order, the SOA composite starts up successfully as it will always have the abstract WSDL reference - After all, at design/compile time, the only thing that a SOA composite requires is the abstract WSDL definition. Only at runtime does the composite would require a concrete WSDL to invoke the right service.
Now, how do we let the design & runtime environments know what service reference (abstract/concrete) to use?
After storing the referenced abstract WSDLs & XSDs in the MDS repository, make the following changes to effect this;
1. Update the import statements in your composite XML to refer the WSDL/XSDs from concrete references to abstract ones;
<import namespace="http://www.oracle.com/orderprocess"
location="oramds:/apps/orderprocess/common/orderprocess_submitorder.wsdl" importType="wsdl"/>
2. Update the service wsdl location to MDS abstract WSDL reference as the soa engine would only look at this element to look up & start the services;
<reference name="SubmitOrder_OrderProcess" ui:wsdlLocation="oramds:/apps/orderprocess/common/orderprocess_submitorder.wsdl">
Leave the WSDL URL in the binding layer intact (to refer to concrete WSDL) because at runtime, the bindings will be used to invoke the actual web service.
To read more about abstract & concrete WSDLs, I recommend you to read my previous blog post here
How to store these artifacts in MDS repository? Ways to do it along with step-by-step instructions in my next post. Here it is!
I am carefully using "Might" here because, the SOA composite under consideration might refer to a service which could be down when the composite was started. This happens because;
The SOA server doesn't know of the service dependencies that a SOA composite has.
For instance let us consider a SOA composite A referencing external services B, C & D deployed on the same server instance. Ideally, we would like to have a service startup order where the services B, C & D are started ahead of composite A.
But that is not the reality as there is no way to set the service startup priority on the SOA server. It wouldn't be a nice idea to weave this setting at the server level as well because, consider a cyclic dependency issue where composite A references composite B and vice versa which would be too complex & cause instability.
This is a classic case for any SOA environment and the issue here is because the concrete WSDL references are used in the SOA composite to connect with the external services.
Now the question is how do we resolve these service dependency issues?
Answer lies in leveraging the SOA infrastructure capability. If you look closely into any SOA composite (source code), there will be a set of common services that will be referenced from the metadata store (MDS);
<import namespace="http://xmlns.oracle.com/bpel/workflow/taskService"
location="oramds:/soa/shared/workflow/TaskServiceInterface.wsdl"
importType="wsdl"/>
These service definitions are stored in the MDS repository which is available all the time for the SOA services to reference provided the underlying DB is up & running. You can check this for yourself by establishing a SOA MDS repository connection from the JDeveloper resource palette.
Similarly, as a best practice you can store all the abstract WSDL definitions of the referenced services in the MDS repository & reference them in your SOA composite. This way whenever the server tries to start the services, irrespective of the service startup order, the SOA composite starts up successfully as it will always have the abstract WSDL reference - After all, at design/compile time, the only thing that a SOA composite requires is the abstract WSDL definition. Only at runtime does the composite would require a concrete WSDL to invoke the right service.
Now, how do we let the design & runtime environments know what service reference (abstract/concrete) to use?
After storing the referenced abstract WSDLs & XSDs in the MDS repository, make the following changes to effect this;
1. Update the import statements in your composite XML to refer the WSDL/XSDs from concrete references to abstract ones;
<import namespace="http://www.oracle.com/orderprocess"
location="oramds:/apps/orderprocess/common/orderprocess_submitorder.wsdl" importType="wsdl"/>
2. Update the service wsdl location to MDS abstract WSDL reference as the soa engine would only look at this element to look up & start the services;
<reference name="SubmitOrder_OrderProcess" ui:wsdlLocation="oramds:/apps/orderprocess/common/orderprocess_submitorder.wsdl">
Leave the WSDL URL in the binding layer intact (to refer to concrete WSDL) because at runtime, the bindings will be used to invoke the actual web service.
To read more about abstract & concrete WSDLs, I recommend you to read my previous blog post here
How to store these artifacts in MDS repository? Ways to do it along with step-by-step instructions in my next post. Here it is!