Inconsistency of JAX-WS Service Implementation Bean

Apr 17, 2011 by

Bottom line : Different JAX-WS runtime may take different approach in managing the life cycle of JAX-WS service implementation bean. JAX-WS RI takes a Servlet-like approach but WebSphere choose the different one.

Many years ago, my team leader at the time asked me what library we should pick for parsing our XML data. He said what he had in his mind were Xerces, Xalan and JAXP and he personally thought that JAXP is the fastest. I don’t recall my answer but I remember that I didn’t correct him at the time. The thing is that JAXP is just a specification but Xerces and Xalan are implementation so the two categories can’t be compared.

The world of Java is like this; full of specifications. A specification will be implemented by vendors. The ideal concept is that you can write your program based on a standard specification and the program will be able to run on any implementations and on any platforms. Well, we all know that it is far from perfect. Sometimes, a specification is not so clear or it is full of details but only the supernatural-brain developers can understand it. There are always grey areas that various implementations behave differently and it’s up to debate whether the behaviors are allowed by the spec.

Let’s look at the thing related to this specification headache that I want to talk about.

@WebService
public class NewsProvider {
    public NewsProvider(){ log("NewsProvider instance created");  }

    @PostConstruct
    public void init(){ log("NewsProvider-@PostConstruct called"); }

    @PreDestroy
    public void destroy(){ log("NewsProvider-@PreDestroy called"); }

    @WebMethod
    public String getProviderName() throws InterruptedException{
        log("getProviderName()");
        return "Devguli.com";
    }

    private void log(String msg){
        System.out.println(msg + " : hashCode=" + hashCode()
                + ", Thread=" + Thread.currentThread().getName());
    }
}

The above primitive code-first service implementation bean is a kind of code that may be found on typical JAX-WS tutorials. I think every Java web developers are well familiar with this pattern of managed component life cycle. In the old days, there may be an interface for us to implement but these days we can just use annotations to mark the hook for initializing our component, the method that implement the business logic and the hook for cleanup logic. It is just like the pattern of using init(), service() and destroy() methods of Servlet. When I start learning JAX-WS, I didn’t even bother to find more information about those annotations. I thought just a short example code was enough for me to guess how it worked. If you run the above code on JAX-WS RI then it looks just like Servlet.

Apr 16, 2011 5:05:49 PM com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextInitialized INFO: WSSERVLET12: JAX-WS context listener initializing
NewsProvider instance created : hashCode=16904839, Thread=http-8084-1
NewsProvider-@PostConstruct called : hashCode=16904839, Thread=http-8084-1
getProviderName() : hashCode=16904839, Thread=http-8084-2
getProviderName() : hashCode=16904839, Thread=http-8084-4
getProviderName() : hashCode=16904839, Thread=http-8084-1
getProviderName() : hashCode=16904839, Thread=http-8084-5
getProviderName() : hashCode=16904839, Thread=http-8084-3
getProviderName() : hashCode=16904839, Thread=http-8084-3
getProviderName() : hashCode=16904839, Thread=http-8084-5
getProviderName() : hashCode=16904839, Thread=http-8084-4
getProviderName() : hashCode=16904839, Thread=http-8084-1
NewsProvider-@PreDestroy called : hashCode=16904839, Thread=http-8084-1
Apr 16, 2011 5:16:06 PM com.sun.xml.ws.transport.http.servlet.WSServletDelegate destroy
INFO: WSSERVLET15: JAX-WS servlet destroyed
Apr 16, 2011 5:16:06 PM com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextDestroyed
INFO: WSSERVLET13: JAX-WS context listener destroyed

JAX-WS runtime will create only one instance of Newsprovider and share it between all request threads. The @PostConstruct method of the instance will be called before it is considered ready to serve its client via getProviderName() method. The @PreDestroy method will be called before the hosting web application is stopped or undeployed.

Note: The above output is the result of running NewsProvider as a Servlet-based web services on Tomcat. When I first experienced this problem, I was developing my project using Netbeans and GlassfishV2. We learned of the problem in our system test which was executed on WebSphere.

If this is the same programming model as of Servlet then it is quite natural for us to initialize expensive resource in @ PostConstruct method. I did just like that and got strange errors or performance drop when I ran my project on WebSphere. The output below show how our NewsProvider behave on WebSphere.

SystemOut O NewsProvider instance created : hashCode=1715234364, Thread=WebContainer : 0
SystemOut O NewsProvider-@PostConstruct called : hashCode=1715234364, Thread=WebContainer : 0
SystemOut O getProviderName() : hashCode=1715234364, Thread=WebContainer : 0
SystemOut O NewsProvider instance created : hashCode=707537452, Thread=WebContainer : 1
SystemOut O NewsProvider-@PostConstruct called : hashCode=707537452, Thread=WebContainer : 1
SystemOut O getProviderName() : hashCode=707537452, Thread=WebContainer : 1
SystemOut O NewsProvider instance created : hashCode=1346654276, Thread=WebContainer : 2
SystemOut O NewsProvider-@PostConstruct called : hashCode=1346654276, Thread=WebContainer : 2
SystemOut O getProviderName() : hashCode=1346654276, Thread=WebContainer : 2
SystemOut O NewsProvider instance created : hashCode=475012176, Thread=WebContainer : 3
SystemOut O NewsProvider-@PostConstruct called : hashCode=475012176, Thread=WebContainer : 3
SystemOut O getProviderName() : hashCode=475012176, Thread=WebContainer : 3

WebSphere will create a new instance of service implementation bean for each request. You can see that this will definitely cause a big problem if we perform initializing of some expensive resources there in @ PostConstruct method.

Another thing that I haven’t been able to figure it out yet is that the @PreDestroy hasn’t been called at all even when the web application has been stopped and undeployed. I personally don’t think that WebSphere treats @PreDestroy as optional. It’s too strange that the initializing method has been called but the cleanup has been ignored. I will blog about this if I can find more information about it.

Specification

Servlet specification has stated clearly in SRV.2.2 Number of Instances :

For a servlet not hosted in a distributed environment (the default), the servlet container must use only one instance per servlet declaration

Both JAX-WS and JSR109 specifications don’t seem to directly state the rule of number of instance but in the 5.3.2.4.2 Web container programming model for JAX-WS ( JSR 109), there is a bullet says:

A Service Implementation must be a stateless object. A Service Implementation Bean must not save client specific state across method calls either within the bean instance’s data members or external to the instance. A container may use any bean instance to service a request

From looking at several sections of the spec, I got a feeling that JAX-WS containers are allowed to create multiple instance of service implementation bean. I couldn’t find any place in the spec suggesting that @PreDestroy can be ignored though.

Addressing the inconsistency

To address this problem, I personally prefer initialing and cleanup all components in ServletContextListener since the behavior of it is quite consistent in all Servlet container. I will make service implementation bean a light weight and stateless class so JAX-WS runtime may choose to created many instance of it. The Bean will just pass web services parameter to the real business logic implementation.

read more

Related Posts

Share This

Debugger is your friend

Apr 16, 2011 by

Bottom Line: I have listed my top reasons for why debugger is really useful

Debugger has always been a big help for me. It is one of the main tools I uses in my day-to-day work, both in coding and troubleshooting. One great thing about debugger is that you can get big benefit form it just by using some simple features like step-over or step-into. I don’t quite get it why debugger hasn’t been used as much as it should be (or may be it’s just where I work that debugger is underused). I have listed my top reasons for the question of why we should utilize debugger

1. Debugger can show you what EXCATLY is happening.

This may be the most obvious reason. The ability to see the actual current value at each execution step is great. I have seen many posts on technical forum asking why a small code snippet doesn’t work like expected. Example of these kind of questions are “Why does my loop run forever?” or “Why I got NullPointerException”. The problematic program is often quite small and primitive. Well, if you are good at reading source code then you may able to trace from the output back to root cause. But if you are not, or your code just too hard to read then why don’t you run the code with debugger and see why that expression doesn’t return false so your loop run forever

Sometimes, I get frustrated with this kind of questions. The answer can be found just by using debugger. It’s more effective and faster than posting question on forum and wait for reply next day later

2. Finding the Happy Path

This is my favorite reasons for using debugger. It’s useful when I have to deal with unfamiliar modules of my project or when I am trying to get some information form third-party framework. I don’t want to fully understand everything in the code I am working with. I just need enough information that enables me to proceed. The benefits of debugger in this category are two folds.

Stepping through components according to default configuration

A program may contain many configurations. A different set of configurations may result in different implementations or different modules glued together at runtime. I may not familiar with the framework perform configuration parsing or some configurations are derived from several values. I don’t want to read all this code for starting up the program. I have a business logic that I am interested in. I just want to know that if I run the program with default configurations, what the class performing the logic is. When I see abstract factory class, I may not want to know how it retrieves the real implementation. I just want to jump right to the implementation code. With debugger, I can just step over the parts that I don’t interested in and try step-into the part that I think might lead me to the actual implementation according to the default configuration

Stepping through Happy Path
The Happy Path, in my definition, means the default path that runs successfully without unexpected thing. It is the execution path on which a program will spend most of its time.

A program contains a lot of conditional branches which dispatch execution to different paths. An execution path may be used only when a special component is present or when a program is in a specific state like suspended or when the program has been run on a specific type of runtime. Again, I don’t want to understand all the possible paths. I can just step-over each expression to see that Happy Path for a use case scenario. With debugger I can filter out a lot of information that is not directly effect the usage scenario I am interested right now.

You may think that this is not much useful because you can guess the Happy Path by just reading the code. All competent developers are good at reading source code to get the knowledge of how the system works. If you see something like:

if( throwable != null){ //….}

if( processor.configureWith(Interceptor.PRE_PROSESSOR ) ){ //…}

Then it is quite easy to guess. Unfortunately, not all developers like to keep their code clean and easy to read. If the code is something like:

if( slot.length > 0 && attributedList.contains(currentSymbol) && link.nextLink != null){
    //….
}
 

You may need some time to see when each variable is in a specific state to know if this code is a part of Happy Path or it’s for another scenario of requesting.

3. Visualize code execution

Writing code needs imagination. Programmers perform some level of design in their head then translate it to source code. Reading code sometimes needs more imagination than writing it, especially when you are not the one who developed the code base. Programmers will load a chunk of code into their brains, execute it line-by-line trying to figure out what the code is doing while keeping values of all variables on the current stack trace in their mind at the same time. I think the ability of visualizing code execution is essential. When I have to deal with the code that I am not familiar with or read a complicated logic, I sometimes use debugger to help me visualize how the code works

For example, I am doing self-study on Continuation-Passing Style. I found a short and nice java example program showing who to find factorial value of a number using CPS

public class Factorial {
    public static void main(String[] args) {
        int n = 3;
        int factorial = faci(n,
                new Cont() {
                    public int k(int v) {
                        return v;
                    }
                });
        System.out.println(factorial);
    }

    static int faci(int n, Cont cont) {
        while (n != 0) {
            cont = new FacCont(n, cont);
            n--;
        }
        return cont.k(1);
    }
}

interface Cont {
    int k(int v);
}

class FacCont implements Cont {

    private final int n;
    private final Cont cont;

    public FacCont(int n, Cont cont) {
        this.n = n;
        this.cont = cont;

    }

    public int k(int v) {
        return cont.k(n * v);
    }
}

A bright and fast-brain developer may read the example and able to figure everything out in instantly. Sadly, I am not that kind of developers. I used debugger to see the actual value in each step to help me understand it faster. I have stepped into faci() method and went through executions until I went out of while loop. What I saw at this point was a chain of FacCont object

The FactCont instance #64 contained variable n with value 1 and a reference to FactCont instance #63

The FactCont instance #63 contained variable n with value 2 and a reference to FactCont instance #62

It went on like this through the chain

The I stepped into the first call of k() method ( at the line > return cont.k(1); )

1*1 = 1 so the value 1 had been sent to the next FactCont in the chain.

2*1 = 2 so the value 2 had been sent to the next FactCont in the chain.

3*2 = 6 so the value 6 had been sent to the next FactCont in the chain.

Now, I knew what was going on. FactCont encapsulates the continuation; the next execution that need to be done. In the build-up code in while-loop, a continuation has been passed to another continuation to form a series of execution

Note: I am not expert in CPS. If I understand it wrong then feel free to comment

4 Cross Check some facts with my brain

Human brain is incredible. Sometimes, it’s effective and innovative. Sometimes’ it’s so stupid and un-reliable. Have you ever had a moment that you spent a large amount of time finding simple little ridiculous thing that caused a bug in your system. In a good day that your mind is quite clear, you may need just 5 minute to spot it out. But in the day before release date or the day you just hear from the manager that your bonus may not be what you have expected then you may look at the root cause 10 times and still don’t be able to figure it out

This brain dysfunction can occur even with a few line of code. I remember a time when I spent half an hour trying to figure out what went wrong in a JUnit test method with 10 line of code. Apparently, I have performed assertion on the wrong object

Debugger doesn’t directly solve this problem. I use it as a tool to crosscheck that the things in my mind is the same as the things that are actually happening in the execution. If I have spent some time unsuccessfully finding some thing in my code then I may switch to run it with debugger and see if my brain has play a trick with me or not

Those are all my top reasons for using debugger. I am sure there are more useful usage scenarios of it. I think most competent developers are making a heavy use of it already so I will just encourage those novices to give it a try. Debugger is your friend

read more

Related Posts

Share This

XML Special Characters

Feb 23, 2011 by

A couple weeks ago, QA team of my project has reported that there was a defect in a module I have developed. The module is a part of our web services for distributing news data. The inbound execution flow is quite simple; the module accept SOAP request from client, transform it to a proprietary XML format of our backend server then send the transformed request to the backend news engine. The characteristic of the defect is that the users can not use string containing XML special characters as a search keyword e.g. they can not query news headlines containing “S&P500”. The news engine could not parse the requests causing exception on the backend server.

It’s a pretty well known fact that there is a set of special characters that must be properly escaped using entity reference before an XML instance that contains these characters can be consumed by any standard XML parser. These characters are apostrophe ( ‘ ), ampersand ( & ), quotation mark ( ” ), less-than symbol ( < ) and greater-than symbol ( > ). Normally, we don’t need to inspect all characters of our string data manually. All decent XML libraries should be able to handle the task for us. For example, JAX-WS stub internally uses JAXB for message parsing so you can just set “S&P500” directly as a search keyword.

NewsProvider_Service service = new NewsProvider_Service();
NewsProvider provider = service.getNewsProviderPort();
List<String> hls = provider.getNewsHeadlines("companies:S&P500");

JAXB will escape the “&” character using “&” entity reference to form a valid XML document. The actual SOAP string sent through network will look like:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:getNewsHeadlines xmlns:ns2="http://ws.news.devguli/">
            <query>companies:S&amp;P500</query>
        </ns2:getNewsHeadlines>
    </S:Body>
</S:Envelope>

The receiver at the other end of this communication must also use XML libraries to parse the message to get back the original “companies:S&P500” string.

It was not too hard to figure out that there was something wrong with the code responsible for creating the messages between my web services and the backend server. I must have done something that let the characters out un-escaped. What I didn’t quite understand was that the error occurred only when the search keyword contained “<” or “&” character. The rest of the special characters could be sent to the backend server just fine. I thought it was something about implementation dependent behavior of each XML libraries so I tried playing with various API and found that all standard Java XML libraries perform escaping only for “<”, “>” and “&”. I have to admit I haven’t noticed this before.

public class Main {
    public static void main(String[] args) throws Exception {
        String msg = " [ < ], [ > ],  [ \" ] , [ & ], [ ' ]";
        StringWriter writer = new StringWriter();

        writeDOM(msg, writer);
        System.out.println("DOM Output = " + writer);

        writer = new StringWriter();
        writeJAXB(msg, writer);
        System.out.println("JAXB Output = " + writer);

        writer = new StringWriter();
        writeSTAX(msg, writer);
        System.out.println("StaX Output = " + writer);
    }

    public static void writeDOM(String msg, Writer writer) throws Exception{
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = builder.newDocument();

        Element data = doc.createElement("Data");
        data.appendChild( doc.createTextNode(msg) );

        doc.appendChild( data);

        Transformer tr = TransformerFactory.newInstance().newTransformer();
        tr.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        tr.transform( new DOMSource(doc.getDocumentElement()) , new StreamResult(writer) );
    }

    public static void writeJAXB(String msg, Writer writer) throws Exception{
        QName qn = new QName("Data");
        JAXBElement<String> elem = new JAXBElement<String>(qn, String.class, msg);

        JAXBContext ctx = JAXBContext.newInstance(String.class);
        Marshaller m = ctx.createMarshaller();
        m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        m.marshal(elem, writer);
    }

    public static void writeSTAX(String msg, Writer writer) throws Exception {
        XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);

        xmlWriter.writeStartElement("Data");
        xmlWriter.writeCharacters(msg);
        xmlWriter.writeEndElement();
        xmlWriter.close();
    }
}

The above code show that JAXB, DOM and StAX are all output the same string; “ [ &lt; ], [ &gt; ], [ " ] , [ &amp; ], [ ' ]”. I tried to gather for more information and found a post on StackOverflow that Jon Skeet (you must have heard the name if you are a regular at the site) had post a valuable reply to answer the question.

From section 2.4 of the XML 1.0 spec (5th edition)

“The ampersand character (&) and the left angle bracket (<) must not appear in their literal form, except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section. If they are needed elsewhere, they must be escaped using either numeric character references or the strings "&" and "<" respectively. The right angle bracket (>) may be represented using the string “>”, and must, for compatibility, be escaped using either “>” or a character reference when it appears in the string “]]>” in content, when that string is not marking the end of a CDATA section.”

The above paragraph states that escaping “<” and “&” is the must. This explains why, in my cases, the exception occurred only when the request contains search keyword with those two characters but the requests with keyword containing “>” works just fine.

For the greater-than character, it seems like the rules are a bit relax. In writing-out operation, XML libraries “must” escape “>” character if the libraries want to produce XML instance that compatible with SGML standard (superset of XML standard). I can see all standard Java XML libraries do just like that but I am not sure it’s because this compatibility concern or it’s just a good practice to do so. In reading-in operation, the “>” characters in the raw xml string don’t need to be escaped. XML libraries are able to parse a file containing the string content as shown below successfully.

<Data> Special text A > B </ Data>

There is one exception. If the greater-than character is part of the string “]]>” but the string doesn’t form a proper CDATA section then the “>” character must be escaped.

<Data> Special text  ]]> </Data>  // cause parsing error
<Data> Special text  ]]&gt; </Data>  // valid XML
<Data><![CDATA[ Special text]]></Data> // valid XML

I have to say this small defect teach me a lot about escaping special characters in XML.

Root cause

I will write about the root cause of this defect here in case you are interested how my module make uses of XML libraries but still has a hole that let those special characters out un-escaped. The reason is that the module contains a part that construct XML document by just appending string together. The messages using in web services are JAXB object and I have a requirement to marshal some JAXB objects to XML string but with different namespace. Since namespace information is the inherent property of JAXB which can’t be modified so I have to marshal those object to SAX content handler and manipulate namespace information in the handler instead.

public static String overrideNameSpace(JAXBElement<?> jaxb)
throws JAXBException{
        Marshaller m = JAXBContext.newInstance("com.devguli").createMarshaller();

        StringBuffer xml = new StringBuffer();
        String nsPrefix = "news";

        NameSpaceOverriderHandler handler = new NameSpaceOverriderHandler (nsPrefix);
        m.marshal( jaxb , new SAXResult(handler) ); 

        xml.append("<" + nsPrefix + ":Root xmlns:" + nsPrefix + "='http://devguli.com/news'>");
        xml.append(handler.getOutputXML() );
        xml.append("</" + nsPrefix + ":Root>");

        return xml.toString();
    }

public class NameSpaceOverriderHandler extends DefaultHandler {

    private final String nsPrefix;
    private final StringBuilder outputXml;

    public NameSpaceOverriderHandler(String nsPrefix) {
        this.nsPrefix = nsPrefix;
        this.outputXml = new StringBuilder();
    }

    public void startElement(String uri, String localName, String qName, Attributes atts)
    throws SAXException {
        outputXml.append("<" + nsPrefix + ":" + localName + serializeAllAttributes(atts) + ">");
    }

    public void endElement(String uri, String localName, String qName)
    throws SAXException {
        outputXml.append("</" + nsPrefix + ":" + localName + ">");
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        outputXml.append(ch, start, length);
    }

     ………
     ………

    public String getOutputXML() {
        return outputXml.toString();
    }

}

You can see in the characters() method of SAX callback that I just appended all characters directly without checking whether the char array contained XML special characters or not.

read more

Related Posts

Share This

JAXB Binder and XPath

May 14, 2010 by

I came across javax.xml.bind.Binder when I was reading SOA Using Java Web Services (excellent book). I had never used this class before so I set out to find how the class could be used. I found that the class hadn’t been mentioned as much as the classes like Marshaller or UnMarshaller but it was very useful.

Binder is usually used to perform partial binding; unmarshalling JAXB object from a part of XML DOM tree. JAXB specification states three use cases of the class. Two are related to partial binding and another one is about the capability of using XPath navigation. It is the last one that I am interested in the most because I actually have a module of my product that I can make use of this technique perfectly.

Below is the XML schema I have created just to simulate the functionality of the module.

<schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://ws.news.com/query"
    xmlns:tns="http://ws.news.com/query"
    elementFormDefault="qualified"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <element name="Query" type="tns:Query"/>

    <complexType name="Query">
    	<sequence>
    		<element name="TimeOut" type="int"/>
    		<element name="Hit" type="int"/>
    		<element name="Filter" type="tns:Filter"/>
    	</sequence>
    </complexType> 

    <complexType name="Filter">
		<group ref="tns:Searchable"/>
	</complexType>

	<element name="And" type="tns:BooleanExpr"/>
	<element name="Or" type="tns:BooleanExpr"/>

	<group name="Searchable">
		<choice>
			<element name="Company" type="string"/>
			<element name="Section" type="string"/>
			<element name="TitleText" type="string"/>
			<element name="TitleAndBodyText" type="string"/>
			<element ref="tns:And"/>
			<element ref="tns:Or"/>
		</choice>
	</group>

	<complexType name="BooleanExpr">
		<sequence>
			<group ref="tns:Searchable" minOccurs="2" maxOccurs="unbounded"/>
		</sequence>
	</complexType>
</schema>

The schema describes request format of a kind of search engine. Users are able to search for item that associated with metadata; Company/Section or search for item that contains a particular string. In my real production code, it’s a news server. The interesting thing is that the schema allow user to group searchable indexes using boolean operator like And, Or. The boolean operators can also be comprise of sub boolean operators allowing the request to grow with no limit of the depth of content tree.

The functionality of the module I’ve mentioned is to extract all occurrences of JAXB object correspondent to , perform decoration on the content of the indexes then replace the original content with the newly decorated one. Below is an example of a simple request.

<Query xmlns="http://ws.news.com/query"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<TimeOut>10</TimeOut>
	<Hit>60</Hit>
	<Filter>
		<Or>
			<And>
				<Or>
					<Section>News</Section>
					<Section>Announcement</Section>
					<Section>Product</Section>
				</Or>
				<Company>BBL.BK</Company>
			</And>
			<And>
				<Or>
					<Section>News</Section>
					<Section>Announcement</Section>
					<Section>Product</Section>
				</Or>
				<Company>PTT.BK</Company>
			</And>
			<And>
				<Section>Trade</Section>
				<Company>SCB.BK</Company>
				<Company>MSFT.O</Company>
				<Company>IBM.N</Company>
			</And>
		</Or>
	</Filter>
</Query>

Manipulating JAXB object is normally easier than operating on low level DOM. But traversing through the whole JAXB object hierarchy is not much better than traversing DOM tree. Especially when the JAXB object we are working with is not quite straightforward. Let’s look at the generated BooleanExpr class for example.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BooleanExpr", propOrder = {
    "searchable"
})
public class BooleanExpr {

    @XmlElementRefs({
        @XmlElementRef(name = "Or", namespace = "http://ws.news.com/query", type = JAXBElement.class),
        @XmlElementRef(name = "TitleAndBodyText", namespace = "http://ws.news.com/query", type = JAXBElement.class),
        @XmlElementRef(name = "TitleText", namespace = "http://ws.news.com/query", type = JAXBElement.class),
        @XmlElementRef(name = "Section", namespace = "http://ws.news.com/query", type = JAXBElement.class),
        @XmlElementRef(name = "And", namespace = "http://ws.news.com/query", type = JAXBElement.class),
        @XmlElementRef(name = "Company", namespace = "http://ws.news.com/query", type = JAXBElement.class)
    })
    protected List<JAXBElement<?>> searchable;

public List<JAXBElement<?>> getSearchable() {
        if (searchable == null) {
            searchable = new ArrayList<JAXBElement<?>>();
        }
        return this.searchable;
    }
}

The concept of data binding between Java and XML is not a perfect world. XML is a very large and complex standard. It’s very difficult if not impossible to define mapping between Java representation and the whole XML information set seamlessly. Some XML artifacts are not able to be mapped to Java with all XML constraints 100% preserved.

Content in BooleanExpr is a choice model group which combines with the maxOccurs=”unbounded” constraint to make the getSearchable() method doesn’t look so nice. Traversing through this BooleanExpr need some checking to see what is the object being operated on.

public static void handleBooleanExpr(BooleanExpr expr){
  List<JAXBElement<?>> searchableList = expr.getSearchable();
  for(JAXBElement<?> elem : searchableList){
  if( elem.getName().equals(andQname ) || elem.getName().equals(orQname )){
	handleBooleanExpr( (BooleanExpr)elem.getValue() );

   }else{
	if( elem.getName().equals(companyQname ) ){
		decorate(elem);
	}
   }
  }
}

I am using just one choice model group in the example because I don’t want to make it too complicated. You may be able to guess that the code to traverse JAXB object will get bloated quickly if there are three or more choice model groups.

If our JAXB object was DOM document then XPath is the clear choice for this kind of task. But if I want to use DOM then I have to marshall the JAXB object to DOM, apply XPath query to perform decoration then unmarshall the modified DOM back to JAXB object. I need to repeat this round-trip processing every time I want to use XPath on the request. It would be nice if I can operate on the request both with JAXB object and XPath. JAXB Binder allows you to do just that.

public void decorateCompany(Query query) throws JAXBException, XPathExpressionException{
		Binder<Node> binder = _ctx.createBinder();
		Node queryDOMView = createBlankDOMDocument(true);  

		//Marshall Query object to a blank DOM document.
		//Binder will maintains association between two views.
		QName qname = new QName("http://ws.news.com/query", "Query");
		binder.marshal( new JAXBElement<Query>(qname, Query.class, query)  , queryDOMView);

		//Search for all occurrences of Company using XPath.
		XPath xpath = XPathFactory.newInstance().newXPath();
		xpath.setNamespaceContext( new QueryNamespaceContext());
		NodeList compList = (NodeList)xpath.evaluate("//query:Company", queryDOMView, XPathConstants.NODESET);

		//Perform decoration
		for(int i=0; i<compList.getLength(); i++){
			Node comp = compList.item(i);
			comp.setTextContent( decorate( comp.getTextContent() ));
		}

		//Synchronize the changes back to Query object.
		binder.updateJAXB(queryDOMView);

	}

	public Node createBlankDOMDocument(boolean namespaceAware) {
		DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
		fact.setNamespaceAware(namespaceAware);
		DocumentBuilder builder;
		try {
			builder = fact.newDocumentBuilder();

		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		}

		return builder.newDocument();
	}

Binder maintains the association between JAXB object and its correspondent XML information set. You can bind Query object to DOM document then modify JAXB object and update the modification to the associated DOM. Or you can modify the DOM tree and then synchronize the changes back to JAXB object. This will give us the best from both worlds. It’s easy to get simple properties like Hit or TimeOut from Query object and I also have option to use low level XML manipulation like XPath to search for particular information from the whole Query object graph.

read more

Related Posts

Share This

I don’t know what exactly web services are

May 11, 2010 by

Back in my days at university, if anybody asked me or my friends “what is the difference between web application and web services” then the answers would be exactly the same; “web application is human-to-machine interaction but web services are machine-to-machine interaction”. I don’t recall how I and my friends got to remember the answers but we all had the perception that it was the most preferable answer. At the time, web services were very new. Tools and concept related to the topic were not matured yet especially for Java world which was quite late for the web services train. My self-study involved a lot of reading, trying to guess what exactly web services were. The perception of web services in my mind was that it was something very advanced involving many technologies working together to overcome all those problems that had been troubling distributed computing for a long time.

My professor once gave an assignment to the class to think of use-cases that could be implemented as web services. I recalled having an argument with one of my friend about this assignment. He suggested that a simple thing like providing basic information to client could be implemented as web services. I didn’t recall what exactly he suggested but it was so simple and contrasted strongly with my perception of web services at the time. We had discussion and I kept telling him his idea was not web service. He finally asked me “what are web services then” and I didn’t know what to answer.

One characteristic associated with web services at its early state was the capability of performing dynamic integration with other systems. A service provider could look up for a potential collaborator from UDDI server and performed some kind of binding to integrate the functionality of the collaborator into the service provider. A book portal web services might look up for book store web services at runtime to find the cheapest price for a particular book order. This just-in-time integration was the reason that I hesitated to accept that the idea of my friend could be called web services. I felt like the idea was just a simple request/reply scenario. It didn’t feature the great web services vision at all.

Years have passed. The technologies around web services have become more matured.
I am now less interested in finding the definition of web services and more interested in learning what each web services technology actually does. I am well familiar with WSDL, SOAP, JAX-WS JAXB and the other java web services specifications. Having something that I can actually play with gives me more confident feeling on what web services are about. I still don’t have one universal definition for web services and don’t think I will ever able to come up with one. But I can tell you with confidence what a particular web services technology does and what it doesn’t do.

Looking back when I started learning web services, I wonder if the vision of just-in-time integration has ever been realized at all. How is it possible for two parties with no common understanding to dynamically integrate with each other to form business services? Let’s say I am writing a book portal program. The program dynamically looks up for a collaborator and gets back BarnesAndNoble.wsdl. How can the program automatically know what operation defined in the WSDL file should be called to get current price of a book? If the operation accept request message as an xml element with type string, should the program fill in the name of the book or the ISBN? It seems like this kind of integration is impossible without a shared understanding or predefined protocol between two parties. It is strange that these questions had never entered my head when I was still in my university at all. I just thought that this thing could be done. I just needed to learn more to know how it worked.

I have recently come across an interesting article; Web Services: It’s So Crazy, It Just Might Not Work. The author has stated a very interesting point saying that “Parseable != Interoperable”. The fact that web services use XML as data format doesn’t automatically make all web services interoperable. XML may be an open standard which can be parsed in any platform but web services are not only required to be able to parse XML messages, it also need to understand the meaning of the messages as well.

“At best, XML makes it possible for businesses or developer groups to share data, provided they agree on the semantics of that data in advance. This is not to say XML is not an enormous advance. It plainly is. However, its advance lies in aiding data interoperability where shared semantics can be assumed. It does nothing at all to create semantic interoperability.”

What I believe web services are about
I may not know what exactly web services are but I can tell you what I believe web services are about

System Integration: We expose our system as web services because we want other systems on whatever platform to integrate with our system with less pain. The ultimate goal is easy integration and not anything else so you should keep you product manager from going out to claim this new technology is going to make your product run faster.

Machine-to-machine interaction: what is the reason of using web services to implement a simple use-case like searching books based on certain simple criteria, given the fact that the use-case can be done by a normal web application.

You may implement the book searching system as a web application which users can access via web browser. A user may see a text field with “Criteria” label in front of it, he type it some criteria and click submit button to get search result. This communication is between human and your web application. But if you choose to expose your application as a web services then you expect users to write a piece of code to connect to your system and call the search service programmatically. A user may be building a book price comparing system which connects to various book providers.

A lot of XML: If you are good at web services development then you are definitely good at XML programming.

read more

Related Posts

Share This