Main BLOGGER
Google
WWW THIS BLOG
Tuesday, April 25, 2006
 
Java dynamic class loading issue

Resource:

 

The thread to discuss how to add (only) jar files into JVM just like it is added in classpath during start up.

http://forum.java.sun.com/thread.jspa?threadID=300557&start=0&tstart=0

 

This link talks about how to dynamically plug in/out jar files (the best way)

http://java.sun.com/products/jndi/tutorial/beyond/misc/index.html

 

 

A more detailed white paper is available at

http://www.javageeks.com/Papers/ClassForName/index.html

 

Quoted abstract:

Abstract:

Dynamic loading of Java classes at runtime provides tremendous flexibility in the development of enterprise systems. It provides for the basis of "application servers", and allows even simpler, lighter-weight systems to accomplish some of the same ends. Within Java, dynamic loading is typically achieved by calling the forName method on the class java.lang.Class; however, when Class.forName is naively called from within an Extension, strange errors can occur. This paper describes why those errors occur, and how Java2 provides two facilities, one a modification to the forName syntax, and the other, called the "Thread context ClassLoader", to avoid them. This paper assumes you are passingly familiar with Java Reflection, and have at least a general idea of what Java ClassLoaders are and how they are used within Java code.

Keywords:Java ClassLoaders Extensions Threads

Following is the core code for invokeMethod

    public ReturnValue invokeMethod(

            String moduleName, String className, String methodName, Object[] methodParams)

    {

        //!!!!!check moduleName/className/methodName, undone

        ClassLoader prevCl = Thread.currentThread().getContextClassLoader();

       

        ReturnValue retVal = new ReturnValue();

        retVal.success = false;

        try {

            File cwd = new File (workDir);

            System.out.println("current work dir: "+cwd.getCanonicalPath());

            String fileSeparator = System.getProperty("file.separator");

 

            String xsharpCodePackageLocation = cwd.getCanonicalPath()+fileSeparator+moduleName+".jar";

            File xsharpJar = new File(xsharpCodePackageLocation);

            File implJar = new File(implAssemblyLocation);

           

            // add .jar to class loader

            URL[] urls = new URL[1];

            urls[0]=xsharpJar.toURL();

 

            ClassLoader urlCl = URLClassLoader.newInstance(urls,prevCl);

            Thread.currentThread().setContextClassLoader(urlCl);            

            Class thisClass = Class.forName(moduleName+"."+className,true,urlCl);

            Object iClass = thisClass.newInstance();

            Method m[] = thisClass.getDeclaredMethods();

            for (int i=0; i<m.length;i++)

            {

                if (methodName.equals(m[i].getName()))

                {

                    m[i].setAccessible(true);

                    retVal.result =  m[i].invoke(iClass, methodParams);

                    retVal.success = true;

                }

            }

        }

        catch (Exception e) {

            retVal.info = e.toString();

        }finally

        {

            Thread.currentThread().setContextClassLoader(prevCl);     

        }

        return retVal;

    }

 

 

 

 

 

 

 

 


Monday, April 24, 2006
 
gt4 and jwsdp-1.5 jar difference list

In GT4 grid service implementation, in order to use client stub generated by jwsdp1.5, we have to copy the following jar files from jwsdp1.5 to gt4.

 

Details:

${jwsdp1.5}/jaxrpc/lib/jaxrpc-api.jar

${jwsdp1.5}/jaxrpc/lib/jaxrpc-impl.jar

${jwsdp1.5}/jaxrpc/lib/jaxrpc-spi.jar

 

${jwsdp1.5}/jwsdp-shared/lib/activation.jar

${jwsdp1.5}/jwsdp-shared/lib/mail.jar

 

${jwsdp1.5}/saaj/lib/saaj-api.jar

${jwsdp1.5}/saaj/lib/saaj-impl.jar

 


Sunday, April 23, 2006
 
WSRF.NET trouble list

The root cause why in WSRF.NET we can not use object, and object[] is due to the wrong type and element name generated by WSRF.NET

 

      In generated MCWSRFPortType.wsdl

 

Change tns:Object to xsd:anyType

Change name=”Object” to name=”anyType”

 

----------Original -----------------

    <xsd:complexType name="Object" />

      <xsd:complexType name="ArrayOfObject">

        <xsd:sequence>

          <xsd:element type="tns:Object" name="Object" minOccurs="0" maxOccurs="unbounded" />

        </xsd:sequence>

      </xsd:complexType>

      <xsd:complexType name="ReturnValue">

        <xsd:sequence>

          <xsd:element type="xsd:boolean" name="success" />

          <xsd:element type="tns:Object" name="result" />

          <xsd:element type="xsd:string" name="info" />

        </xsd:sequence>

      </xsd:complexType>

 

 

----------Changed -----------------

      <xsd:complexType name="ArrayOfObject">

        <xsd:sequence>

          <xsd:element type="xsd:anyType" name="anyType" minOccurs="0" maxOccurs="unbounded" />

        </xsd:sequence>

      </xsd:complexType>

      <xsd:complexType name="ReturnValue">

        <xsd:sequence>

          <xsd:element type="xsd:boolean" name="success" />

          <xsd:element type="xsd:anyType" name="result" />

          <xsd:element type="xsd:string" name="info" />

        </xsd:sequence>

      </xsd:complexType>

 

 

Then update the web reference on the client side (Do not change service side)

 

 


Saturday, April 22, 2006
 
Play with java SOAPElement in JAX-RPC xsd:anyType

In JAX_RPC, xsd:anyType is mapped to javax.xml.soap.SOAPElement

Here is the java function to convert an int to SOAPElement

 

    public static SOAPElement int2SOAPElement(String tagName, int value)

    {

       try{            

         SOAPFactory sf = SOAPFactory.newInstance();    

         SOAPElement e = sf.createElement(tagName);

         String xsi = "http://www.w3.org/2001/XMLSchema-instance";

         Name xsiTypeString = sf.createName("type", "xsi", xsi);

         e.addAttribute( xsiTypeString, "xsd:int" );

         e.addTextNode((new Integer(value)).toString());

         return e;      

       }catch(Exception e)

       {

          System.out.println ( "int2SOAPElement, exceptioin: "+ e.toString() );

          return null;

       }

}

 

 

For example

 

    <!-- method input: array of object -->

    <xsd:complexType name="ArrayOfObject">

      <xsd:sequence>

         <xsd:element type="xsd:anyType" name="Object" minOccurs="0" maxOccurs="unbounded" />

       </xsd:sequence>

    </xsd:complexType>

 

   <!-- invoke mobile code -->

    <xsd:element name="invokeMethod">

      <xsd:complexType>

        <xsd:sequence>

          <xsd:element type="xsd:string" name="moduleName" />

          <xsd:element type="xsd:string" name="methodName" />

          <xsd:element type="tns:ArrayOfObject" name="methodParams" />

        </xsd:sequence>

      </xsd:complexType>

    </xsd:element>

 

 

          String MODULE = "CmmCode.Math";

          String METHOD = "main_entry";

          ArrayOfObject aoo= new ArrayOfObject();

          SOAPElement e = int2SOAPElement("Object",1234);

          aoo.setObject(new SOAPElement[]{e});

          retVal = service.invokeMethod(MODULE, METHOD, aoo );   

 

 

the result xml is

 

<?xml version="1.0" encoding="UTF-8"?>

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"

     xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/"       

     xmlns:ns0="http://www.cs.binghamton.edu/mcws">

   <env:Body>

       <ns0:invokeMethod>

           <moduleName>CmmCode.Math</moduleName>

           <methodName>main_entry</methodName>

           <methodParams>

                <Object xsi:type="xsd:int">1234</Object>

           </methodParams>

      </ns0:invokeMethod>

   </env:Body>

</env:Envelope>


Friday, April 21, 2006
 
How to use Java SOAPElement

 

1. javax.xml.soap à saaj.jar

Interface SOAPElement

http://java.sun.com/j2ee/1.4/docs/api/javax/xml/soap/SOAPElement.html

 

This package is defined in the SOAP with Attachments API for JavaTM (SAAJ) 1.1 specification.

 

SOAPElement could be used as Element

Because

public interface SOAPElement

extends Node, Element

 

 

2. Using xsd:anyType to Represent XML Documents in a Service Interface: Design Details

 

https://bpcatalog.dev.java.net/nonav/soa/doc-anytype/design.html

 

 

 

public class PurchaseOrder {    

    private String poId;
    private Calendar createDate;
    private Address shipTo;
    private Address billTo;
    private LineItem[] items;   

    public PurchaseOrder() {}   

    public PurchaseOrder(String poId, Calendar createDate,
            Address shipTo, Address billTo, LineItem[] items) {

        this.poId = poId;
        this.shipTo = shipTo;
        this.createDate = createDate;
        this.billTo = billTo;
        this.items = items; 
    }

    ...

     public SOAPElement toXMLSOAPElement(boolean wrapper) {
        SOAPElement soapElem = null;
        try {
            //construct the DOM tree
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            docBuilderFactory.setNamespaceAware(true);
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            Element  poElem = doc.createElement("PurchaseOrder");
            if(wrapper){
                Element  docElem = doc.createElement("BusinessDocumentRequest");
                doc.appendChild(docElem);
                docElem.appendChild(poElem);
            } else{
                doc.appendChild(poElem);
            }
            Element  elem = doc.createElement("poId");
            elem.appendChild(doc.createTextNode(poId));
            poElem.appendChild(elem);
            elem = doc.createElement("createDate");
            elem.appendChild(doc.createTextNode((new SimpleDateFormat("MM-dd-yy")).format(createDate.getTime())));
            poElem.appendChild(elem);
            elem = doc.createElement("shipTo");
            poElem.appendChild(shipTo.toDOM(doc, elem));
            elem = doc.createElement("billTo");
            poElem.appendChild(billTo.toDOM(doc, elem));
            for(int i = 0; i < items.length; ++i){
                poElem.appendChild(items[i].toDOM(doc));
            }
           
            //create a SOAPElement
            SOAPElement parent = SOAPFactory.newInstance().createElement("dummy");
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer();
            transformer.transform(new DOMSource(doc), new DOMResult(parent));
            soapElem = (SOAPElement) parent.getChildElements().next();
        } catch(TransformerException te) {
            te.printStackTrace(System.err);
            throw new RuntimeException(te.getMessage(), te);
        } catch(ParserConfigurationException pce) {
            pce.printStackTrace(System.err);
            throw new RuntimeException(pce.getMessage(), pce);
        } catch(SOAPException se) {
            se.printStackTrace(System.err);
            throw new RuntimeException(se.getMessage(), se);
        }
        return soapElem;
}


 
Java web service portal

1.  Patterns and Strategies for Building Document-Based Web Services

 

http://java.sun.com/developer/technicalArticles/xml/jaxrpcpatterns/index.html

 

 

2.  Writing A JAX-RPC Client from WSDL (quite old though, but the build.xml is useful)

 

http://www.descriptor.com/articles/web-services/wsdlclient.html

 

 

Here is my tutorial

 

1. get the wsdl file in place  ../wsdl/mcws.wsdl

 

2. use the following bat to generate stubs.

C:\tomcat50-jwsdp\jaxrpc\bin\wscompile -gen:client -d stub config.xml –keep

 

3. generate the config.xml

<?xml version="1.0" encoding="UTF-8"?>

<configuration

    xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">

   <wsdl location="../wsdl/mcws.wsdl" packageName="mcwsClient"/>

</configuration>

 

4. create the ant build.xml

 

<?xml version="1.0"?>

 

<project default="run-client">

 

   <!-- define the destination directories -->

   <property name="jwsdp-home"

      value="C:/tomcat50-jwsdp"/>

     

   <property name="jaxrpc-home"

      value="${jwsdp-home}/jaxrpc"/>

 

   <property name="saaj-home"

      value="${jwsdp-home}/saaj"/>

          

   <!-- setup the CLASSPATH -->

   <path id="classpath">

      <fileset dir="${jwsdp-home}/common/lib">

        <include name="*.jar" />

      </fileset>

 

      <fileset dir="${jaxrpc-home}/lib">

        <include name="*.jar" />

      </fileset>

 

      <fileset dir="${saaj-home}/lib">

        <include name="*.jar" />

      </fileset>

 

      <fileset dir="${jwsdp-home}/jwsdp-shared/lib">

        <include name="*.jar" />

      </fileset>

     

      <fileset file="${jwsdp.home}/fastinfoset/lib/FastInfoset.jar"/>

      <fileset file="${jwsdp.home}/sjsxp/lib/jsr173_api.jar"/>     

    </path>

     

   <!-- define the "build" target -->

   <target name="build">

     <javac srcdir="."

            destdir="./classes" >

        <classpath refid="classpath"/>

        <classpath>

            <pathelement location="."/>

        </classpath>

     </javac>

   </target>

  

   <!-- define the "run-client" target -->

   <target name="run-client" depends="build">

      <java classname="Client" fork="true">

        <classpath refid="classpath"/>

        <classpath>

            <pathelement location="./classes"/>

        </classpath>

      </java>

   </target>

 

   <!-- define the "run" target -->

   <target name="run" >

      <java classname="Client" fork="true">

        <classpath refid="classpath"/>

        <classpath>

            <pathelement location="./classes"/>

        </classpath>

      </java>

   </target>

  

</project>

 

5. build client

C:\> ant build

 

6. run client

C:\> ant run

 


Wednesday, April 19, 2006
 
interoperability between GSOAP and .NET

The key point is about namespace.

 

1. How to use gsoap DOM parser to generate xsd:anyType node

 

  extern "C" ACE_Svc_Export soap_dom_element factory()

  {

    xsd__int ret = main_entry();

    struct soap soap;

    soap_init(&soap);

    soap_set_imode(&soap, SOAP_DOM_NODE);

    xsd__int domval=ret ; //we have to use this type

soap_dom_element retDomVal(&soap, "mcws", NULL, &domval, SOAP_TYPE_xsd__int);

//”mcws” ----- must use the namespace which is the same defined in WSDL

// NULL  ------ must be NULL else this name will be used as TAG name in the soap message

    return retDomVal;

  }

 

 

2. the result soap message generated by GSOAP, which is exactly specified in WSDL. Such that .NET client can parse it out correctly.

<?xml version="1.0" encoding="UTF-8"?>

 

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:mcws="http://www.binghamton.edu/mcwsDocu">

  <SOAP-ENV:Body>

      <mcws:invokeCodeResponse>

            <mcws:value xsi:type="xsd:int">49</mcws:value>

            <mcws:ret>0</mcws:ret>

      </mcws:invokeCodeResponse>

  </SOAP-ENV:Body>

</SOAP-ENV:Envelope>

 

3. GSOAP wsdl

 

<message name="installCodeResponse">

 <part name="parameters" element="mcws:installCodeResponse"/>

</message>

 

<element name="invokeCodeResponse">

   <complexType>

    <sequence>

     <element name="value" type="xsd:anyType" minOccurs="1" maxOccurs="1"/>

     <element name="ret" type="xsd:int" minOccurs="1" maxOccurs="1"/>

    </sequence>

   </complexType>

  </element>

 

 

4. Debugging && trouble shooting

4.1 on GSOAP side, define DEBUG in the compiler for example –DDEBUG

Then we will get SEND.log and RECV.log in the current working directory

 

4.2 on DOTNET side, we can add code into client stub (generated by wsdl.exe or “update web reference”

 

Override public partial class McwsDocu : System.Web.Services.Protocols.SoapHttpClientProtocol

.

protected override XmlReader GetReaderForMessage(SoapClientMessage message, int bufferSize)

 

Add references

    using System.Net;

    using System.IO;

    using System.Xml;

    using System.Text;

 

Implementation

            /* copy stream to another stream*/

        private void Copy(Stream streamFrom, Stream streamTo)

        {

            TextReader reader = new StreamReader(streamFrom);

            TextWriter writer = new StreamWriter(streamTo);

            String line;

            line = reader.ReadLine();

            while (line != null)

            {

                writer.WriteLine(line);

                line = reader.ReadLine();

            }

            writer.Flush();

        }

        /* will generate log file for incoming soap message to c:\\log.txt */

        protected override XmlReader GetReaderForMessage(SoapClientMessage message, int bufferSize)

        {

            MemoryStream m = new MemoryStream();

            Copy(message.Stream, m);

 

            m.Seek(0, SeekOrigin.Begin);

            Double now = System.DateTime.Now.ToOADate();

            FileStream fs = new FileStream("c:\\log.txt", FileMode.OpenOrCreate, FileAccess.Write);

            StreamWriter w = new StreamWriter(fs);         // create a Char writer

            w.BaseStream.Seek(0, SeekOrigin.End);         // set the file pointer to the end

 

            TextReader reader = new StreamReader(m);

            String line;

            while ((line = reader.ReadLine()) != null)

            {

                w.WriteLine(line);

            }

            w.Flush();

            w.Close();

 

            m.Seek(0, SeekOrigin.Begin);

 

 

            XmlTextReader xmlreader;

            xmlreader = new XmlTextReader(m);

            xmlreader.ProhibitDtd = true;

            xmlreader.Normalization = true;

            xmlreader.XmlResolver = null;

            return xmlreader;

        }

 



Powered by Blogger

Google
WWW THIS BLOG