Thursday, December 1, 2011

Weblogic 10.3 installment and Cluster setup - 4

--- verify and troubleshoot ---

add these configuration in window host file
192.168.0.84            vm.mydomain.com
192.168.0.85            vm.mydomain.com

download InMemRepClient.war and install it in this cluster servers

modify weblogic.xml to support session replicate in cluster servers


<?xml version="1.0" encoding="UTF-8" ?>
   <weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90">
   <session-descriptor>
       <persistent-store-type>replicated</persistent-store-type>
  </session-descriptor>
</weblogic-web-app>

http://vm.portal.com:7005/InMemRepClient/Session.jsp

if show down either server, the value in session is always there.


troubleshoot:

take note need to open the inbound/outbound Port,let's say 5556, 7005,etc, in windows servers

...

Weblogic 10.3 installment and Cluster setup - 3

--- cluster setup ---

1.start new doman admin console










2. open admin console URL http://localhost:7001/console/login/LoginForm.jsp

key in user name/password to log on as administrator






click 'New' button to add new clustering servers



















specify server name, server listen address, server listen port, choose 'Yes,create a new cluster for this server' and click Next


















key in the cluster name and click Finish
>>>> do above steps again to add the other server























click Next












click Finish

click Clusters to check the new cluster added above.






click 'Machines' and click 'New' button to add new machines which will be worked in a cluster 'CPortal_Cluster'
























click OK to exit and do the same thing to add 'CPortal_Machine_2'







click the hyperlink 'CPortal_Machine_1' and open 'Node Manager' tab to configure node manager on this machine



















click Save to save the configuration for node manager on machine CPortal_Machine_1

choose 'Servers' tab , click 'Add' button













select a server to tie to this machine, click Next











click the hyperlink 'CPortal_Machine_2' and do the same thing above








































reconfigure node manager (do this for both machine)
click above two machine hyperlink and open 'Monitor' tab to check the status is 'Reachable' or not
open E:\bea\wlserver_10.3\common\nodemanager\nodemanager.properties
SecureListener=false

run command services.msc to open window service list to restart node manager service











>>>>> copy the whole folder E:\bea\user_projects on machine 192.168.0.84 to machine 192.168.0.85

click above two machine hyperlink and open 'Monitor' tab to check the status is 'Reachable' or not


























found there is an exception on machine 192.168.0.85.
go to this machine, and open log file E:\bea\wlserver_10.3\common\nodemanager\nodemanager.log

<INFO> <Loading domains file: E:\bea\WLSERV~1.3\common\nodemanager\nodemanager.domains>
<INFO> <Loaded node manager configuration properties from 'E:\bea\WLSERV~1.3\common\nodemanager\nodemanager.properties'>
<INFO> <Plain socket listener started on port 5556>
<Warning> <I/O error while reading domain directory: java.io.FileNotFoundException: Domain directory 'E:\bea\wlserver_10.3\common\nodemanager' invalid (domain salt file not found)>
java.io.FileNotFoundException: Domain directory 'E:\bea\wlserver_10.3\common\nodemanager' invalid (domain salt file not found)
            at weblogic.nodemanager.server.DomainManager.initialize(DomainManager.java:81)
            at weblogic.nodemanager.server.DomainManager.<init>(DomainManager.java:53)
            at weblogic.nodemanager.server.NMServer.getDomainManager(NMServer.java:252)
            at weblogic.nodemanager.server.Handler.handleDomain(Handler.java:218)
            at weblogic.nodemanager.server.Handler.handleCommand(Handler.java:109)
            at weblogic.nodemanager.server.Handler.run(Handler.java:66)
            at java.lang.Thread.run(Thread.java:619)

how to resolve the problem ?

open domain file E:\bea\WLSERV~1.3\common\nodemanager\nodemanager.domains on both servers and compare, found the domain file on machine 192.168.0.85 lost one item

cportal_domain=E\:\\bea\\user_projects\\domains\\cportal_domain

add it into nodemanager.domains on machine 192.168.0.85 and restart the node manager service on this machine.

go back to check the status on machine 192.168.0.85 and found it is reachable.

Weblogic 10.3 installment and Cluster setup - 2

--- create a new domain ---

1. install weblogic on both server


2. go to 192.168.0.84

3. click 'Configuration Wizard'












4. choose 'Create a new weblogic domain'
































key in user name and password for this domain admin
















































customise these settings later, choose 'No' and click 'Next'
















specify domain name and location, click 'Create'















click Done button to exit.

Weblogic 10.3 installment and Cluster setup - 1

--- weblogic installment ---

env:
jdk 1.6.0_23
window server 2008 enterprise 64-bit OS

server ip
192.168.0.84
192.168.0.85
 
> install weblogic server on 192.168.0.84

double click installer file server103_win32.exe


















click 'Next'

















specify BEA home directory,click 'Next'

















choose 'Custom' and click Next

















unselect 'Workshop' and cilck Next

















select bundled JDK and click Next
















click Next
















choose 'Yes' and use default port 5556 as node manager listen port number , click Next

















click Next
















click Next

































click Done to complete the installation.

> do the same steps to install weblogic server on 192.168.0.85

Wednesday, May 18, 2011

How to convert XSD to XML or vice versa


- Preparation

1. JAXB library

download JAXB library from http://jaxb.java.net/

execute this jar as

java -jar <jaxb jar name>

On Windows, you can just double-click the jar file to execute.

2. Trang library

http://code.google.com/p/jing-trang/downloads/list


- XSD to XML

1. manually prepare the two XSD files


person.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"  xmlns:address="http://test.xsdxml.com/demo/detail"  elementFormDefault="qualified" targetNamespace="http://test.xsdxml.com/demo/person" xmlns="http://test.xsdxml.com/demo/person" >


<xs:import namespace="http://test.xsdxml.com/demo/detail" schemaLocation="detail.xsd" />

<xs:element name="person">
  <xs:complexType>
     <xs:sequence>
       <xs:element ref="header" />
       <xs:choice>
         <xs:element ref="address" />
         <xs:element ref="contactNo" />
       </xs:choice>
     </xs:sequence>
  </xs:complexType>
</xs:element>
 
<xs:element name="header" >
  <xs:complexType >
    <xs:sequence>
      <xs:element name="timestamp" type="xs:dateTime"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
 
<xs:element name="address">
  <xs:complexType>
    <xs:choice>
      <xs:sequence>
        <xs:element ref="postcode" />
        <xs:element ref="country" />
      </xs:sequence>
      <xs:sequence />
      <xs:element ref="address:detail" />
    </xs:choice>
    <xs:attribute name="name" use="required">
      <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:enumeration value="home" />
        <xs:enumeration value="office" />
     </xs:restriction>
     </xs:simpleType>
    </xs:attribute>
  </xs:complexType>
</xs:element>

<xs:element name="contactNo">
  <xs:complexType>
    <xs:choice>
      <xs:sequence>
        <xs:element ref="mobile" />
        <xs:element ref="fixline" />
      </xs:sequence>
      <xs:sequence />
    </xs:choice>
  </xs:complexType>
</xs:element>

<xs:element name="postcode" type="xs:string" />
<xs:element name="country" type="xs:string" />
<xs:element name="mobile" type="xs:string" />
<xs:element name="fixline" type="xs:string" />
</xs:schema>

detail.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://test.xsdxml.com/demo/detail" xmlns="http://test.xsdxml.com/demo/detail">

<xs:element name="detail">
  <xs:complexType>
     <xs:sequence>
       <xs:element name="street" type="xs:string" />
       <xs:choice>
         <xs:element ref="buildingNo" />
         <xs:element ref="roomNo" />
       </xs:choice>
     </xs:sequence>
  </xs:complexType>
</xs:element>
 
<xs:element name="buildingNo" type="xs:string" />
<xs:element name="roomNo" type="xs:string" />
</xs:schema>


run the command to generate the java classes.

C:\tmp\xjc>xjc person.xsd
parsing a schema...
compiling a schema...
com\xsdxml\test\demo\person\Address.java
com\xsdxml\test\demo\person\ContactNo.java
com\xsdxml\test\demo\person\Header.java
com\xsdxml\test\demo\person\ObjectFactory.java
com\xsdxml\test\demo\person\Person.java
com\xsdxml\test\demo\person\package-info.java
com\xsdxml\test\demo\detail\Detail.java
com\xsdxml\test\demo\detail\ObjectFactory.java
com\xsdxml\test\demo\detail\package-info.java


>> so person object is in package com.xsdxml.test.demo.person, and detail object is in package com.xsdxml.test.demo.detail


2. sample code


package com.xsdxml.test;

import java.io.StringWriter;
import java.util.GregorianCalendar;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import com.xsdxml.test.demo.detail.Detail;
import com.xsdxml.test.demo.person.Address;
import com.xsdxml.test.demo.person.ContactNo;
import com.xsdxml.test.demo.person.Header;
import com.xsdxml.test.demo.person.ObjectFactory;
import com.xsdxml.test.demo.person.Person;

public class JAXBSample {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance("com.xsdxml.test.demo.person");
        ObjectFactory factory = new ObjectFactory();
        // create person instance from ObjectFactory
        Person person = factory.createPerson();
        // create header instance from ObjectFactory
        Header header = factory.createHeader();
        XMLGregorianCalendar cal = DatatypeFactory.newInstance()
                .newXMLGregorianCalendar(new GregorianCalendar(2010, 10, 12));
        cal.setTime(13, 23, 45);
        // give value 2010-10-12T13:23:45 to timestamp
        header.setTimestamp(cal);
        person.setHeader(header);
        // create ContactNo instance from ObjectFactory
        ContactNo contNo = factory.createContactNo();
        contNo.setMobile("123445");
        person.setContactNo(contNo);

        Address address = factory.createAddress();
        address.setName("Home");
        address.setPostcode("112233");
        address.setCountry("myCountry");
        Detail detail = new Detail();
        detail.setStreet("street Name");
        detail.setBuildingNo("building 1");

        person.setAddress(address);

        Marshaller m = jc.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        // marshal to system.o
        m.marshal(person, System.out);
        // marshal to string
        System.out.println("----> " + asString(jc, person));

    }

    public static String asString(JAXBContext pContext, Object pObject)
            throws JAXBException {

        java.io.StringWriter sw = new StringWriter();

        Marshaller marshaller = pContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        marshaller.marshal(pObject, sw);

        return sw.toString();
    }
}


This is the output if run the class.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person xmlns="http://test.xsdxml.com/demo/person" xmlns:ns2="http://test.xsdxml.com/demo/detail">
    <header>
        <timestamp>2010-11-12T13:23:45+08:00</timestamp>
    </header>
    <address name="Home">
        <postcode>112233</postcode>
        <country>myCountry</country>
    </address>
    <contactNo>
        <mobile>123445</mobile>
    </contactNo>
</person>

- XML to XSD


1. manually perpare the XML file

person.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
    <header>
        <timestamp>2010-11-12T13:23:45+08:00</timestamp>
    </header>
    <address name="Home">
        <postcode>112233</postcode>
        <country>myCountry</country>
    </address>
    <contactNo>
        <mobile>123445</mobile>
    </contactNo>
</person>

2. run this command to generate XSD file

java -jar trang.jar person.xml person.xsd


this is the file person.xsd generated by trang

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="person">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="header"/>
        <xs:element ref="address"/>
        <xs:element ref="contactNo"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="header">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="timestamp"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="timestamp" type="xs:dateTime"/>
  <xs:element name="address">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="postcode"/>
        <xs:element ref="country"/>
      </xs:sequence>
      <xs:attribute name="name" use="required" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="postcode" type="xs:integer"/>
  <xs:element name="country" type="xs:NCName"/>
  <xs:element name="contactNo">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="mobile"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="mobile" type="xs:integer"/>
</xs:schema>



Reference URLs

http://www.thaiopensource.com/relaxng/trang.html
http://ws.apache.org/jaxme/release-0.4/manual/ch02s02.html

Friday, January 21, 2011

Develop Web Service With Axis2 #9 - HTTP Basic Authentication in Weblogic

My Environment:
JDK v1.6.x
Axis2 V1.5.4
Weblogic v1.03

1) add 'user'/'user group' in weblogic

login weblogic server administration console

select 'Security Realms' under domain structure on the left of admin console page

click 'myrealm' which is the default realm name in weblogic,and open configuration 'Settings for myrealm'

click tab 'Users and Groups' to add user and user group

click sub-tab 'Groups' first to add one new group

click sub-tab 'Users', and click 'New' button to add new user and key in password here as well.

click the user name which was created above hyperlink, and select 'Groups' tab to assign the user to the user group created above

2) add configuration shown below in web.xml

<security-constraint>
   <web-resource-collection>
      <web-resource-name>mywsapi</web-resource-name>
      <url-pattern>/services/{your service name}</url-pattern>
   </web-resource-collection>
   <auth-constraint>
      <role-name>{user name configured in Weblogic}</role-name>
   </auth-constraint>
</security-constraint>
<login-config>
   <auth-method>BASIC</auth-method>
   <realm-name>myrealm</realm-name>   <-- this is the default realm name in weblogic
</login-config>
<security-role>
   <role-name>{user name configured in Weblogic}</role-name>
</security-role>

3) add configuration shown below in weblogic.xml

<security-role-assignment>
   <role-name>{user name configured in Weblogic}</role-name>
   <principal-name>{user group configured in Weblogic}</principal-name>
</security-role-assignment>

4) on stub side, you need to do more to pass user name and password as follows.

Options opt = _stub._getServiceClient().getOptions();
HttpTransportProperties.Authenticator mbAuth = new HttpTransportProperties.Authenticator();
mbAuth.setUsername("{user name configured in weblogic}");
mbAuth.setPassword("{password configured in weblogic}");
mbAuth.setPreemptiveAuthentication(true);
opt.setProperty(HTTPConstants.AUTHENTICATE, mbAuth);
_stub._getServiceClient().setOptions(opt);

Tuesday, January 11, 2011

Develop Web Service With Axis2 #8 - Troubleshooting while working with Axis2

My Environment:
JDK  v1.6.x
Axis2  v1.5.4
Ant  v1.7.1
Hibernate  v3.3.1
Tomcat  v6.0.26
Weblogic v1.03

1) tomcat can not start up properly if deploy axis2 project to tomcat

I got the errors as follows

SEVERE: Error in dependencyCheck
java.util.zip.ZipException: invalid bit length repeat
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:147)
    at java.util.zip.ZipInputStream.read(ZipInputStream.java:146)

or

Jan 9, 2011 7:35:42 PM org.apache.catalina.core.StandardContext start
SEVERE: Error in dependencyCheck
java.util.zip.ZipException: too many length or distance symbols
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:147)
    at java.util.zip.ZipInputStream.read(ZipInputStream.java:146)

or

org.apache.axis2.deployment.DeploymentException: A ClassNotFoundException error occurred in loading the message receiver

Solution:
You must follow up the build.xml provided by axis2 strictly if you write your own build.xml

For example,

<copy todir="${build.dist.dir}/WEB-INF/lib" filtering="true" overwrite="yes">

if filtering="true", the jar file will be not unzipped properly if pack in war file.

2) can not load hibernate

My .aar structure is as follows

.aar
      /com       --- classes files
      /lib          --- hibernate jar files and other the 3rd jar files
      /META-INF
      hibernate.cfg.xml
      log4j.properties


in services.xml, add the following configuration

<parameter name="ServiceTCCL">composite</parameter>

if using this configuration, axis2 will load jar files under lib folder inside aar


3) log4j

Finally, I found if put log4j.properties in aar, it will not work, the correct location is %WAR%\WEB-INF\classes

4)  jar conflict if deploying to weblogic

These are well-known exceptions if deloying axis2 project into weblogic.

org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken


Solution:
*change the war file struecture

WAR
   |- axis2-web
   |- WEB-INF
          |- classes
                  |- com/xxx    Here is your DAO, business classes, utils,etc
                  log4j.properties
                  hibernate.cfg.xml
                  your own other properties 
          |- conf
                   axis2.xml
          |- lib
                   all axis2-related jar files
                   log4j-related jar files
                   hibernate-related jar files
                   other 3rd party jar files
           |- modules
           |- services
                    yourservice.aar     Only inlcude skeleton classes here, almost generated by axis2
                            com/...../xxxMessageReceiverInOut.class
                            com/...../xxxSkeleton.class
                            META-INF\services.xml
                            META-INF\wsdl.list
                            META-INF\xxxx.wsdl
           web.xml
           weblogic.xml


* in weblogic.xml, should configure

    <container-descriptor>
        <prefer-web-inf-classes>true</prefer-web-inf-classes>
    </container-descriptor>

* in hibernate.cfg.xml, it is not necessary to configure 'hibernate.query.factory_class'

there is a jar ANTLR conflict between hibernate v3.x and weblogic, so someone suggests to configure explicitly 'hibernate.query.factory_class'

for hibernate v3.x query translator,
hibernate.query.factory_class= org.hibernate.hql.ast.ASTQueryTranslatorFactory
for hibernate v2.x query translator
hibernate.query.factory_class= org.hibernate.hql.classic.ClassicQueryTranslatorFactory

It is NOT necessary to do so.

<prefer-web-inf-classes> will ensure weblogic load %WAR%\WEB-INF\lib , let hibernate auto-choose which query translator to use.


5) can not find aar/mar file if deploying to weblogic

need to add aar file name, or mar file name in \services\services.list and \mrodules\modules.list

6) cannot show custom WSDL file, always show auto-generated WSDL file

in your own .aar\META-INF folder to add a file named wsdl.list , and put your wsdl file name in it.

in services.xml ,  <parameter name="useOriginalwsdl">true</parameter>

7) xerces jar file conflict if deploying to weblogic

java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method "org.apache.xerces.dom.ElementImpl.getSchemaTypeInfo()Lorg/w3c/dom/TypeInfo;" the class loader (instance of weblogic/utils/classloaders/ChangeAwareClassLoader) of the current class, org/apache/xerces/dom/ElementImpl, and the class loader (instance of <bootloader>) for interface org/w3c/dom
/Element have different Class objects for the type org/w3c/dom/TypeInfo used in the signature

Solution: remove xercesImpl-2.8.1.jar from axis2\WEB-INF\lib

Tuesday, January 4, 2011

Develop Web Service With Axis2 #7 - Add Custom Soap Header in Response Soap Message

Prev >>> Develop Web Service With Axis2 #6 - Workaround Solution for Custom "Header" on Skeleton/Stub side 

This article will talk about how to add soap headers in response soap message, not work around solution mentioned in previous article.

The approach is to use module/handler to inject the soap headers while responding to consumers.

follow this article Develop Web Service With Axis2 #4 - Axis2 Style Interceptor to create a new module.

------ module class

package mypackage;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisDescription;
import org.apache.axis2.description.AxisModule;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.modules.Module;
import org.apache.neethi.Assertion;
import org.apache.neethi.Policy;

public class SoapHeaderModule implements Module {
     public void init(ConfigurationContext configurationContext,
              AxisModule axisModule) throws AxisFault {
          System.out.println("Initializing the module");
     }

     public void engageNotify(AxisDescription axisDescription) throws AxisFault {

     }

      public boolean canSupportAssertion(Assertion assertion) {
           return false;
      }

       public void applyPolicy(Policy policy, AxisDescription axisDescription)
           throws AxisFault {
       }

        public void shutdown(ConfigurationContext configurationContext)
           throws AxisFault {
       }

}

-------- handler class

package mypackage;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.handlers.AbstractHandler;

public class HeaderOutHandler extends AbstractHandler {
    public InvocationResponse invoke(MessageContext messageContext)
            throws AxisFault {
        // add an Soap header for the outgoing soap message
        SOAPEnvelope soapEnvelope = messageContext.getEnvelope();

        if (soapEnvelope.getHeader() == null) {
            String soapNamespace = soapEnvelope.getNamespace()
                    .getNamespaceURI();
            // creating a soap factory according the the soap namespce uri
            SOAPFactory soapFactory = null;
            if (soapNamespace
                    .equals(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI)) {
                soapFactory = OMAbstractFactory.getSOAP11Factory();
            } else if (soapNamespace
                    .equals(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI)) {
                soapFactory = OMAbstractFactory.getSOAP12Factory();
            } else {
                System.out.println("Unknow soap message");
            }
            soapFactory.createSOAPHeader(soapEnvelope);
        }

        OMNamespace omNamespace = OMAbstractFactory.getOMFactory()
                .createOMNamespace("http://mycompany.com", "myNs");

        SOAPHeaderBlock soapHeaderBlock = soapEnvelope.getHeader()
                .addHeaderBlock("responseId", omNamespace);

        soapHeaderBlock.setText("11223344");

        soapHeaderBlock = soapEnvelope.getHeader().addHeaderBlock(
                "resonseTime", omNamespace);

        soapHeaderBlock.setText(new java.util.Date().toString());

        return InvocationResponse.CONTINUE;
    }
}

-------------------- module configuration file

<module name="CustHeaderModule" class="mypackage.SoapHeaderModule">
<OutFlow>
        <handler name="OutFlowHeaderOutHandler" class="mypackage.HeaderOutHandler">
             <order phase="CustHeaderPhase" />
        </handler>
</OutFlow>
</module>


----------------   modify axis2.xml

    <phaseOrder type="OutFlow">
        <!--      user can add his own phases to this area  -->
        <phase name="soapmonitorPhase"/>
        <phase name="OperationOutPhase"/>
        <phase name="CustHeaderPhase"/>
        <phase name="auditLogPhase"/>
        <!--system predefined phase-->
        <!--these phase will run irrespective of the service-->
        <phase name="RMPhase"/>
        <phase name="PolicyDetermination"/>
        <phase name="MessageOut"/>
        <phase name="Security"/>
    </phaseOrder>

Take note that I put CustHeaderPhase before auditLogPhase, so that inject soap headers first, auditLogPhase show response soap message including soap headers subsequently.

------------- add the module to services.xml

    <module ref="auditLogger"/>
   <module ref="CustHeaderModule"/>



-------- test it.

 <?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header>
    <myNs:responseId xmlns:myNs="http://mycompany.com">11223344</myNs:responseId>
    <myNs:resonseTime xmlns:myNs="http://mycompany.com">Tue Jan 04 17:13:16 CST 2011</myNs:resonseTime>
</soapenv:Header>
<soapenv:Body>
    <ns2:getUserProfileResponse xmlns:ns2="http://axis.test.com/ws">
        <ns2:userProfileResponse>
        <<ns1:age xmlns:ns1="http://bean.axis.test.com/xsd">32</ns1:age>
        <ns1:userName xmlns:ns1="http://bean.axis.test.com/xsd">dddddddddd</ns1:userName>
    </ns2:userProfileResponse>
</soapenv:Body>
</soapenv:Envelope>


============= Reminder ===============
to customize HTTP header is another useful function. refer to
http://www.keith-chapman.org/2008/10/axis2-setting-custom-http-headers-on.html


Example code:

MessageContext responseMessageContext =        MessageContext.getCurrentMessageContext().getOperationContext().getMessageContext(                 WSDLConstants.MESSAGE_LABEL_OUT_VALUE);   
List headers = new ArrayList();  headers.add(new Header(HTTPConstants.HEADER_CONTENT_ENCODING, "identity"));  responseMessageContext.setProperty(HTTPConstants.HTTP_HEADERS, headers);

Monday, January 3, 2011

Develop Web Service With Axis2 #6 - Workaround Solution for Custom "Header" on Skeleton/Stub side

Prev >>> Develop Web Service With Axis2 #5 - Custom Soap Header on Stub side 

It is not straightforward to add <soap:header> to response message on skeleton in axis2.
Someone suggests to write own message receiver, or add soap header by module, and someone suggests to convert header information to HTTP header,etc.


There is a workaround solution to put header information to body. Let's start with code-first approach.

---- define header information

package com.test.axis.bean;

import java.util.Date;

public class Header {

    private String requestId;

   // setter and getter methods
}

----- re-define the interface

package com.test.axis.service;

import com.test.axis.bean.AuthUserRequest;
import com.test.axis.bean.UserInfoRequest;
import com.test.axis.bean.UserInfoResponse;
import com.test.axis.bean.WebServiceFault;

public interface UserServices {
    UserInfoResponse getUserInfo(UserInfoRequest infoRequest) throws WebServiceFault;

    UserInfoResponse authUser(
            AuthUserRequest authRequest)
            throws WebServiceFault;
}

---- define userInfoRequest by this way

package com.test.axis.bean;

public class UserInfoRequest {

   private Header header;
    private String userId;
   
    // setter and getter methods
 }

------ re-define UserInfoResponse object, put header inside as well

package com.test.axis.bean;

import java.util.Date;

public class UserInfoResponse {

    private Header header;
   private String userName;
 
    // setter and getter methods
}

------ generate wsdl based on above java beans and interface

------ request message

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
    <soapenv:Body>
        <ns2:getUserInfo xmlns:ns2="http://axis.test.com/ws">
            <ns2:userInfoRequest>
                <header xmlns="http://bean.axis.test.com/xsd">
                    <requestId>552121</requestId>
                </header>
                <ns1:userId xmlns:ns1="http://bean.axis.test.com/xsd">user111</ns1:userId>
            </ns2:userInfoRequest>
        </ns2:getUserInfo>
    </soapenv:Body>
</soapenv:Envelope>

------ response soap message

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns2:getUserInfoResponse xmlns:ns2="http://axis.test.com/ws">
<ns2:userInfoResponse>
<header xmlns="http://bean.axis.test.com/xsd">
<requestId>552121</requestId>
</header>
<ns1:userName xmlns:ns1="http://bean.axis.test.com/xsd">dddddddddd</ns1:userName>
</ns2:userInfoResponse>
</ns2:getUserInfoResponse>
</soapenv:Body>
</soapenv:Envelope>

Develop Web Service With Axis2 #5 - Custom Soap Header on Stub side

Prev >>> Develop Web Service With Axis2 #4 - Axis2 Style Interceptor 

1) if only add a simple string to header 


--- stub code

OMFactory omFactory =OMAbstractFactory.getOMFactory();
OMNamespace omNamespace = omFactory.createOMNamespace("http://mycompany.org", "myHeader");
OMElement header = omFactory.createOMElement("header", omNamespace);
header.setText("This is a custom soap header");
_stub._getServiceClient().addHeader(header);

-- soap message

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
  <soapenv:Header>
     <myHeader:header xmlns:myHeader="http://mycompany.org">
        This is a custom soap header
     </myHeader:header>
   </soapenv:Header>
   <soapenv:Body>
      <ns2:getUserInfo xmlns:ns2="http://axis.test.com/ws" />
    </soapenv:Body>
</soapenv:Envelope>

2) to use OMElement object to encapsulate soap header

--- stub code

OMElement header1 = AXIOMUtil.stringToOM("<header1><systemId>system-011</systemId></header1>");
OMElement header2 = AXIOMUtil.stringToOM("<header2><requestTime>"+new java.util.Date()+"</requestTime></header2>");
 _stub._getServiceClient().addHeader(header1);
 _stub._getServiceClient().addHeader(header2);

--- soap message

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header>
   <header1>
       <systemId>system-011</systemId>
   </header1>
   <header2>
       <requestTime>Mon Jan 03 14:29:00 CST 2011</requestTime>
   </header2>
</soapenv:Header>
<soapenv:Body>
<ns2:getUserInfo xmlns:ns2="http://axis.test.com/ws" />
</soapenv:Body>
</soapenv:Envelope>

3. SOAPHeaderBlock

--- stub code

OMNamespace omNamespace = OMAbstractFactory.getOMFactory()
                    .createOMNamespace("http://myCompany.com", "headerNs");
SOAPHeaderBlock header1 = OMAbstractFactory.getSOAP12Factory()
                    .createSOAPHeaderBlock("header1", omNamespace);
header1.addChild(AXIOMUtil.stringToOM("<header123>header content</header123>"));
_stub._getServiceClient().addHeader(header1);

---- soap message

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header>
    <headerNs:header1 xmlns:headerNs="http://myCompany.com">
         <header123>header content</header123>
    </headerNs:header1>
</soapenv:Header>
<soapenv:Body>
<ns2:getUserInfo xmlns:ns2="http://axis.test.com/ws" />
</soapenv:Body>
</soapenv:Envelope>

Reference
http://wso2.org/library/3156