Showing posts with label SOA. Show all posts
Showing posts with label SOA. Show all posts

Monday, 10 April 2017

Modifying the Namespace prefix while marshaling the JAXB object

There would be times when we want to see a meaningful name to namespace prefixes given by JAXB marshaling API. By default for any QName which does not have prefix attribute, JAXB will give prefix in this format 'ns<number>' eg: ns0, ns1 etc.

To achieve it, there is a property called MarshallerProperties.NAMESPACE_PREFIX_MAPPER ("eclipselink.namespace-prefix-mapper"); this is for JAXB reference implementation by eclipselink. If it is a different vendor, the property name will vary. For this key, we need to set a value as an instance of org.eclipse.persistence.oxm.NamespacePrefixMapper class.


  jc = JAXBContext.newInstance("com.mypackage.jaxb");
  m = jc.createMarshaller();
  m.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER,
                new NamespacePrefixMapper() {
                   // Map to store the namespace and prefixes
                    Map<String, String> namespacePrefixMap = new HashMap<>();
                        @Override
                        public String getPreferredPrefix(String namespaceuri, String suggestion, boolean requiredPrefix) {      
                            String prefix = namespacePrefixMap.get(namespaceuri);
                            if (null == prefix) {
                               prefix = "myprefix" + suggestion;
                               namespacePrefixMap.put(namespaceuri, prefix);
                             }
                             return prefix;
                        }
               });

Monday, 26 December 2016

Exposing Endpoints in both SOAP1.0 and SOAP1.2 version in Oracle SOA Suite

Sometimes we want to expose SOAP endpoint URL in both SOAP1.0 and SOAP1.2 versions. In this blog, I am trying to explain how we can achieve it when we expose SOAP endpoints using Oracle SOA Suite.

The configuration to mention the version of SOAP is available in composite.xml file. Whoever worked on creating a SOA project using Oracle SOA Suite would know about composite.xml file, still I will take as an opportunity to explain what composite.xml mean and what it contains.

Composite.xml is an auto generated files which is like a master xml file. This file describes the entire composite assembly of services, service components, references, and wires. 

Composite.xml contains following parts

1. Defines composite name, version and namespaces
2. Importing dependent WSDLs
3. Defining list of services being exposed as an endpoints
4. Composite properties if any
5. Component implementation details
6. References detail of services being used by this composite
7. Wiring between service and components

If we observe the below composite.xml file, we could see the soapVersion attribute in <binding.ws> tag under <service> definition part in composite.xml. This is the one which will be referred by WebLogic server while deploying the composite application and appropriate SOAP service and binding information will be added dynamically to the WSDL document.  

<?xml version="1.0" encoding="UTF-8" ?>
<!-- Generated by Oracle SOA Modeler version 12.1.3.0.0 at [11/24/16 10:38 AM]. -->

<composite name="ThrowingFaults"
           revision="2.0"
           label="2016-11-24_10-38-01_605"
           mode="active"
           state="on"
           xmlns="http://xmlns.oracle.com/sca/1.0"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
           xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
           xmlns:ui="http://xmlns.oracle.com/soa/designer/"
           xmlns:sca-ext="http://xmlns.oracle.com/sca/1.0-ext">
  <import namespace="http://xmlns/ThrowMeFault"
          location="WSDLs/ThrowMeFault.wsdl" importType="wsdl"/>
  <service name="throwmefault_client_ep" ui:wsdlLocation="WSDLs/ThrowMeFault.wsdl">
    <interface.wsdl interface="http://xmlns/ThrowMeFault#wsdl.interface(ThrowMeFault)"/>       <binding.ws port="http://xmlns/ThrowMeFault#wsdl.endpoint(throwmefault_client_ep/ThrowMeFault_pt)" soapVersion="1.1"/>
  </service>
  <service name="throwmefault12_client_ep" ui:wsdlLocation="WSDLs/ThrowMeFault.wsdl">
    <interface.wsdl interface="http://xmlns/ThrowMeFault#wsdl.interface(ThrowMeFault)"/>
    <binding.ws port="http://xmlns/ThrowMeFault#wsdl.endpoint(throwmefault_client/ThrowMeFault_pt)" soapVersion="1.2">     
    </binding.ws>
  </service>
  <property name="productVersion" type="xs:string" many="false">12.1.3.0.0</property>
  <property name="compositeID" type="xs:string" many="false">cfeae6cc-91a3-4ef0-a143-be9a62514b5b</property>
  <component name="ThrowMeFault" version="1.1">
    <implementation.bpel src="BPEL/ThrowMeFault.bpel"/>
    <componentType>
      <service name="throwmefault_client" ui:wsdlLocation="WSDLs/ThrowMeFault.wsdl">
        <interface.wsdl interface="http://xmlns/ThrowMeFault#wsdl.interface(ThrowMeFault)"/>
      </service>           
    </componentType>
    <property name="bpel.config.transaction" type="xs:string" many="false">required</property>
  </component>
  <wire>
    <source.uri>throwmefault_client_ep</source.uri>
    <target.uri>ThrowMeFault/throwmefault_client</target.uri>
  </wire>
  <wire>
    <source.uri>throwmefault12_client_ep</source.uri>
    <target.uri>ThrowMeFault/throwmefault_client</target.uri>
  </wire>
</composite>

If we do not mention the version of SOAP in composite.xml then the default one would be SOAP1.1.

Tuesday, 5 July 2016

Using MDS (MetaData Service) API to list all the deployed composites in SOA

The jar mdsrt.jar contains all the necessary API to explore contents inside MDS (MetaData Store). Unfortunately there is no javadoc for the classes inside this jar, atleast I couldn't find couple of blog links to understand the usage of some MDS APIs.

In this blog, my intention is to show how to read a file using MDS API.

The first task is to write the adf-mds-confix.xml file which contains the configuration information to connect to MDS and the <metadata-namespaces> contains the name of the folders whose sub-folders or files that will be accessed using MDS API.

<?xml version = '1.0' encoding = 'UTF-8'?>
 <adf-config xmlns="http://xmlns.oracle.com/adf/config">
    <adf-mds-config xmlns="http://xmlns.oracle.com/adf/mds/config">
       <mds-config version="11.1.1.000" xmlns="http://xmlns.oracle.com/mds/config">
                <persistence-config>
                         <metadata-namespaces>
                                 <namespace path="/soa/shared" metadata-store-usage="soa-infra-store">
                                 </namespace>
                                 <namespace path="/apps" metadata-store-usage="soa-infra-store"/>
                         </metadata-namespaces>
                         <metadata-store-usages>
                                <metadata-store-usage id="soa-infra-store">
                                        <metadata-store xmlns="http://xmlns.oracle.com/mds/config"
                                                                        class-name="oracle.mds.persistence.stores.db.DBMetadataStore">

                                                        <property name="jndi-datasource" value="jdbc/mds/owsm"/>

                                                          <property name="partition-name" value="soa-infra"/>
                                         </metadata-store>
                                  </metadata-store-usage>
                          </metadata-store-usages>

      </persistence-config>
 </mds-config>
     </adf-mds-config>
  </adf-config>




    /**
     * This API returns the list of deployed composited in SOA server
     * 
     * @return list of composites
     */
    public List<Composite> getDeployedComposites() {
        List<Composite> deployedList = new ArrayList<>();
        try {
            // Read the adf-mds-config.xml config file which has the configuration information for reading a file from MDS            
            File adfConfigPath = new File(configPath.toString());
            MDSConfig config = new MDSConfig(adfConfigPath.toURL());
            
            // Create MDS instance & Session
            MDSInstance mdsInstance = MDSInstance.getOrCreateInstance("TargetInstance", config);
            MDSSession mdsSession = mdsInstance.createSession(new SessionOptions(null, null, new CustConfig(new CustClassListMapping[0])), null);
            
            // Form a query which reads the deployed-composites.xml file
            NameQueryImpl query = new NameQueryImpl(mdsSession, ConditionFactory.createNameCondition("/deployed-composites", "deployed-composites.xml", true));
            Iterator<DocumentResult> r = query.execute();
            while(r.hasNext()) {
                DocumentResult dr = r.next();                
                if (dr.getAbsoluteName().endsWith(".xml")) {
                    MetadataObject mdObj = mdsSession.getMetadataObject(dr.getAbsoluteName());
                    
                    // Get the DOM object of the deployed-compisite.xml
                    Document doc = mdObj.getDocument(true);
                    
                    // Access the composite name from the xml
                    // eg: <composite-series name="default/ScheduledProcessFlow" default="default/ScheduledProcessFlow!2.0">
                    NodeList nList = doc.getElementsByTagName("composite-series");
                    for (int i=0;i<nList.getLength();i++) {
                            Node node = nList.item(i);
                            String str = node.getAttributes().getNamedItem("default").getNodeValue();
                            
                            // Add composite details to the list
                            deployedList.add(getCompositeObj(str));
                    }                    
                    break;
                }
            }
        } catch(Exception ex) {
           throw new RuntimeException("Unable to read the deployed-composites.xml file " + "\n" + ex.getMessage());
        }
        return deployedList;

    }


Some blog links which I referred


http://oraclemw.blogspot.in/2011/04/working-with-oracle-mds-repository.html

http://amulyamishras-tech-blog.blogspot.in/2013/07/adf-nds-use-mds-api-to-remove.html
http://www.oracle.com/technetwork/developer-tools/jdev/metadataservices-fmw-11gr1-130345.pdf

Wednesday, 18 May 2016

Creating an array of XML element in BPEL

The objective of this post is to generate an XML response which has array of XML element using BPEL.

Problem Statement:

Input to the BPEL process : n / integer
Output from BPEL process : result / String array of length n

Solution:

To solve this problem, we can use <bpelx:append>  which is an BPEL extension function

namespace for bplex is xmlns:bpelx="http://schemas.oracle.com/bpel/extension"

Below is the code snippet where it inserts a node using bpelx:append

<bpel:assign name="InsertResponse">
  <bpelx:append>
    <bpelx:from>

        <result xmlns="http://xmlns.oracle.com/HelloWorlsApp/ArrayOutput/Collection">StringTest
        </result>
    </bpelx:from>
    <bpelx:to bpelx:language="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0" variable="outputVariable" part="payload" query="/client:processResponse"/>
   </bpelx:append>      
 </bpel:assign>


This assignment we can keep it inside a <bpel:while> with a condition like index should be less than the input n.


Sample Input

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
     <ns1:process xmlns:ns1="http://xmlns.oracle.com/HelloWorlsApp/ArrayOutput/Collection">
      <ns1:input>3</ns1:input>
       </ns1:process>
    </soap:Body>
</soap:Envelope>


Sample Output

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
  <env:Body>
<processResponse xmlns="http://xmlns.oracle.com/HelloWorlsApp/ArrayOutput/Collection">
<result>StringTest</result>
<result>StringTest</result>
<result>StringTest</result>
</processResponse>
  </env:Body>
</env:Envelope>


Tuesday, 3 May 2016

elementFormDefault attribute in XSD Schema definition

This attribute (elementFormDefault) is useful when we are defining our own <complexType> in our schema and the main purpose is to decide whether the <element> inside <complexType> should be in targetNamespace or global namespace

Example:
Sample XSD:
<?xml version = '1.0' encoding = 'UTF-8'?>
<xsd:schema xmlns:ns0="http://ticket.com/ns" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://ticket.com/ns">  
   <xsd:complexType name="routeTicket">
      <xsd:sequence>
         <xsd:element name="ticket" type="xsd:string" minOccurs="0"/>
      </xsd:sequence>
   </xsd:complexType>
   <xsd:complexType name="routeTicketResponse">
      <xsd:sequence>
         <xsd:element name="return" type="xsd:string" minOccurs="0"/>
      </xsd:sequence>
   </xsd:complexType>
   <xsd:element name="routeTicket" type="ns0:routeTicket"/>
   <xsd:element name="routeTicketResponse" type="ns0:routeTicketResponse"/>

</xsd:schema>


when elementFormDefault="unqualified"
when elementFormDefault="qualified"
Valid XML for the given XSD:

<?xml version="1.0" encoding="utf-8"?>
<xs:routeTicket xmlns:xs="http://ticket.com/ns">
  <ticket>str1234</ticket>
</xs:routeTicket>

Valid XML for the given XSD:

<?xml version="1.0" encoding="utf-8"?>
<xs:routeTicket xmlns:xs="http://ticket.com/ns">
  <xs:ticket>str1234</xs:ticket>
</xs:routeTicket>

XPATH to access ticket

/xs:routeTicket/ticket

XPATH to access ticket

/xs:routeTicket/xs:ticket


Useful online tools