Sunday, November 21, 2010

Enabling SSL for AXIS2 service and client

We often encounter the satuation where requirement is to consume webservice exposed on https. In this article we will investigate how to consume webservice exposed over https using axis2. First lets see how to enable SSL for AXIS2 services:

Enabling SSL on server side for AXIS2 in tomcat:

You really don't need to do much enable SSL for services deplyed in AXIS2. Just follow how to enable SSL in tamcat.Add following in Server.xml of tamcat.

<Connector
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="test.jks" keystorePass="test123"
clientAuth="false" sslProtocol="TLS"/>


Use axis2 1.5.3 in which axis2.xml has https transportReceiver enabled by default, listening on 8443 port so you don't need any configuration change in axis2.xml.
<transportReceiver name="https"
class="org.apache.axis2.transport.http.AxisServletListener">
<parameter name="port">8443</parameter>
</transportReceiver>

Prior to this version of axis2 was using org.apache.axis2.transport.nhttp.HttpCoreNIOSSLListener as transportReceive which was having issues and not generating https endpoint correctly.

SSL on client side:

Axis2 uses http commons to transfer SOAP message over http. Apache http common uses JSSE(java secure socket extension) library for SSL.
JSSE is integrated with JDK since version 1.4.

Ideally if we just provide end point URL starting with https, SSL connection will be started and we don’t need any additional configuration. Creation of secure connection will be taken care by JSSE. But then trust store and keystore used by the JSSE would be default keystores shipped with JDK.

In the practical/production scenarios user should have capability to choose his truststore/keystore.
user may decide to trust a self signed certificate and keep it his local truststore or different applications may use different keystore/truststore.
Above can be achieved by two ways:
Approach 1:
We can set truststore, password etc in system properties. This will be picked by JSSE in SSL handshake.
Ex.
System.setProperty("javax.net.ssl.trustStore","Your truststore path");
System.setProperty("javax.net.ssl.trustStorePassword","your trust store password");
This approach will not be appropriate for tooling since it sets keystore on JVM level. We should have flexibility where we could attach different keystore/truststore for different axis2 clint running in same JVM.

Approach 2:
Apache commons provide facility which allows us to customize the SSL socket factory responsible for creation of secure socket. By customization I mean ability to use user truststore/keystore in SSL handshake. To achieve it we need to extend SecureProtocolSocketFactory interface. In our custom socket factory implementation user refer its Keystore/Truststore against default keystores.
Apache commons provide a reference implementation class named AuthSSLProtocolSocketFactory for this purpose.

This class takes Truststore/Keystore as argument to constructor which will be referred later while initiating SSLContext. SSLContext is used to create SSL Socket Factory.
In your axis2 client code you need to add following:
Protocol authhttps = new Protocol ("https", new AuthSSLProtocolSocketFactory (new url("keystore URL"), "pwd", newURL("truststore URL"), "pwd"), 443);
Protocol.registerProtocol("https", authhttps);

And you are all set to consume secure webservice.

Saturday, October 16, 2010

Dealing with low disk space problem caused by AXIS2 temp files

Recently I came across interesting scenario where axis2 modules jars file were getting created on every execution of axis2 client code. This was resulting in low disk space since temp directory was flooded with temp jars created by axis2. We can't avoid creation of these jars in temp dir since these are modules jars used by axis2 class loader to load modules class needed to engage axis2 modules. What we can difinitely do is reusing the generated jar files created on first use and deleted these temp file on JVM shut down.

Lets first see how to reuse the temp file generated.

As we know ConfigurationContext object created every time client tries to invoke the service or every time we create ServiceClient instance. To avoid this situation we need to cache ConfigurationContext class once created. We need to modify AXIS2 1.4 ServiceClient code as follows(Highlighted):

ServiceClient#configureServiceClient

if (configContext == null) {
if (ListenerManager.defaultConfigurationContext == null) {
configContext = ConfigurationContextFactory.
createConfigurationContextFromFileSystem(null, null);
ListenerManager.defaultConfigurationContext = configContext;
createConfigCtx = true;
} else {
configContext = ListenerManager.defaultConfigurationContext;
}
}

Now lets try to delete the single set of temp file on JVM shutdown.
AXIS2 engine does the write thing while creating these temp file. it also calls java.io.File#deleteOnExit which tells the JVM to delete these file on exit.
But unfortunately AXIS2 class loader will be referring these files so these could not be deleted by JVM(which is un resolved bug in JVM). To deal with it once you are done with using serviceclient. you have to call ServiceClient#cleanup. Cleanup method looks into temp folder start with _axis2 and deletes all files which are not referred by axis2 which may be present from previous JVM session.
The temp file created in one JVM session will be deleted not on JVM exit but in the nest session of JVM. When you invoke ServiceClient#cleanUp().

AXIS2 1.5 onward the startegy for dealing with temp file is improved. Here responsibility to manage temp files are delegated to class named TempFileManager instead of using java.io.File#createTempFile directly.

This uses TempFileManager#createTempFile which along with temp folder to contain the jars creates another file named tempFolderName suffixed by .lck. On both of these java.io.File#deleteOnExit is called. JVM will not be able to delete the temp folder containing the temp jars but it will be able to delete the .lck file on shout down. Since these is no reference to .lck file. Now on next start up when TempFileManager class is loaded it has static block which will look for all axis2 temp folder for which corresponding .lck file is not present.

The advantage is if you are using AXIS2 1.5 you don't need to call ServiceClient#cleanup to clean these temp file. It will be cleaned up on TempFileManager class loading.

Friday, October 15, 2010

Engaging modules in AXIS2 on client side

Engaging modules at client side gets quite frustrating when you have written stand alone client on eclipse. There are no. of ways you can do that. The easiest one is to change module extensions form .mar to .jar so that you can add them to eclipse class path. You don't have to make any other changes and you can engage module at client side programatically.

suppose you want to engage addressing module, then following code will be sufficient provided you have addressing.jar file in your class path.

ServiceClient sc = new ServiceClient();
sc.engageModule("addressing");

Now lets remove addressing jar from class path and try running the same code. You will get infamous "Unable to engage module : addressing"!

So what if I don't want to change the extension of modules. We need to pass location of module file while creating configuration context as follows.

ConfigurationContext configContext =
ConfigurationContextFactory.createConfigurationContextFromFileSystem("E:/LAB/apache/axis2-1.3-bin/axis2-1.3/repository","E:/LAB/apache/axis2_repo/axis2.xml");
ServiceClient sc = new ServiceClient(configContext,null);
sc.engageModule("addressing");

Engaging modules can be set globally when you pass axis2.xml while creating configuartion context. You need to uncomment <module ref="addressing"/> in axis2.xml. Now sc.engageModule("addressing"); is not needed to engage addressing module. Moreover if you don't want addressing feature for every client request comment <module ref="addressing"/> in axis2.xml and engage module by calling ServiceClient#engageModule when needed.

There is another way to provide modules information at runtime by setting :Constants.AXIS2_REPO and Constants.AXIS2_CONF config properties.

System.setProperty(Constants.AXIS2_REPO, "C:/MyFolder/MySoftwareLab/tools/axis2-1.5.1-bin/axis2-1.5.1/repository");
System.setProperty(Constants.AXIS2_CONF, "your local axis2 path");

Above works because of following code of AXIS2 engine.

if (repoLocation == null) {
//checking wether user has set the system property
repoLocation = System.getProperty(Constants.AXIS2_REPO);
}

if (axis2xml == null) {
// If not, check for a system property setting
axis2xml = System.getProperty(Constants.AXIS2_CONF);

Friday, October 1, 2010

Test your WSDL skills

I have compiled a list of WSDL question which can be used to test one's WSDL understanding. These questions may not cover each area in depth, but can be used to enhance basic understanding of WSDL.

1. What are the extensibilty element required to be added as WSDL extension in case of SOAP binding?

SOAP:Binding > messaging style and transport,
SOAP:Operation> SOAP action and SOAP message style(RPC/Document),
SOAP:body/SOAP:Header/SOAP:Fault > talks about message encoding style(encoded/literal), namespace of elements in body in case of SOAP encoded style,
SOAP:address > tells about web service end point

2. Which elements of WSDL take targetnamespace of WSDL definition?
message, portType, binding

3. Which elements of WSDL doesn't support extension?
message, portType

4. Can I define a schema in types element without targetNamespace?
No, TargetNamespace has to be not null.

5. Can I define targetNamespace of schema in types element different from targetNamespace of WSDL?
Yes, its perfectly legal as long as targetNamespace of schema is specified in definition or in definition of one of the imported WSDL.

6. What the WSDL imports used for?
WSDL import are meant only to import other WSDL and not for importing XML schema.

7. Can I have targetnamespace of imported WSDL different from namespace attribute of import element?

No, It must be same and namespace and location field of import element is mandatory.

8. What should be the sequence for WSDL types and WSDL import element?

Import element is present it should precedes types element.

9. Can I use xml schema import definition to import XML schema form types element of some other WSDL?

No, its not possible.

10. What are the message exchange pattern that an endpoint can support?

Request: endpoint receives a message
Request-Response: Endpoint receives message and send a correlated message.
Solicit-Response: Endpoint send a message and receives a correlated message.
Notification: Endpoint send a message.

11. Can request (one way) MEP send back fault?

No

12. Part definition refers to which part of fault message?

Details

13. Webservice server could not process soap message due to incorrect header, should it send back fault message with fault:detail populated?

No, Fault detail should be populated only if SOAP:Body element of incoming message has invalid data.

14. Can we have more than one binding for given portType?

Yes

15. Can binding element provide address information?

No

16. What are the different type of bindings supported in WSDL?

SOAP, HTTP, MIME. Though BP prohibits use of HTTP and MIME.

17. SOAP:body element has defined namespace attribute, can I tell which style of service it represents?

RPC

18. What is default style, in case style attribute is not mentioned in WSDL?

document

19. Can fault message can have multiple parts?

Fault message must have single part. Message style of soap fault is always assumed to be "Document" since fault don't contain parameters.

Sunday, August 29, 2010

Extending CMIS data model for alfresco repository

My previous blog talks about extending CMIS data model for Open-CMIS in memory repository. In this blog I will explain on extending CMIS content model for alfresco repository.

Alfresco provides mechanism for extending CMIS data model. All we have to do is just register custom data model.

First step would be defining the custom content model. Defined custom content model should follow modelSchema.xsd which can be found under Alfresco\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\model.

Let’s take an example where I want to define custom document type with addition properties.

<type name="Lib:BookHistory">
<title>Book History</title>
<parent>cm:doc</parent>
<properties>
<property name="Lib:BookId">
<type>d:text</type>
<mandatory>true</mandatory>
</property>
</properties>
</type>

Suppose we name this file as LibModel.xml. Complete content of the file is attached at the end of blog.

Now the next step would be registering our content model as extension. For that we need to create a file with suffix context in the name referring to custom model i.e. Lib-model-context.xml.

Name can be anything as long as it has suffix context. Custom model can be referred in the custom file as follows-


<!-- Registration of new models -->
<bean id="extension.dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
<property name="models">
<list>
<value>alfresco/extension/LibModel.xml</value>
</list>
</property>
</bean>

We need to put these xml files in following directory Alfresco\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\extension.

Using custom model in Open-CMIS:

Custom types can be referred with prefix D: and custom properties can be referred as it is in Open-CMIS client API. For example in case of our custom defined model type will be referred as D: Lib:BookHistory and property will be referred as Lib:BookId.

Issue with the alfresco:

Alfresco community edition 3.3 has a bug which doesn’t allow CMIS client to persist values for custom properties in alfresco repository. Fix for this is available in alfresco head build.

Content of LibModel.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Definition of new Model -->
<model name="Lib:LibModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">

<!-- Optional meta-data about the model -->
<description>Someco Model</description>
<author>Optaros</author>
<version>1.0</version>

<!-- Imports are required to allow references to definitions in other models -->
<imports>
<!-- Import Alfresco Dictionary Definitions -->
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
<!-- Import Alfresco Content Domain Model Definitions -->
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
</imports>

<!-- Introduction of new namespaces defined by this model -->
<namespaces>
<namespace uri="http://www.someco.com/model/content/1.0" prefix="Lib" />
</namespaces>

<types>
<!-- Enterprise-wide generic document type -->
<type name="Lib:BookHistory">
<title>Book Histroy</title>
<parent>cm:content</parent>
<properties>
<property name="Lib:BookId">
<type>d:text</type>
<mandatory>true</mandatory>
</property>
</properties>
</type>
</types>

</model>

Content of Lib-model-context.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- Registration of new models -->
<bean id="extension.dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
<property name="models">
<list>
<value>alfresco/extension/LibModel.xml</value>
</list>
</property>
</bean>
</beans>

Sunday, August 15, 2010

How to extend CMIS data model

By going through CMIS doc I got an impression that I should be able to create my custom object type by extending standard object type. That make sense, isn't it. My business model may have some specific data model and for that I should be able to extend standard data model provided by CMIS.

But now the question is how to achieve it? Do you think just adding a custom property.object type in the atom entry you send to create the document will server the purpose?

Let's try it using Open-CMIS client library.

Map parameter = new HashMap();

// connection settings
parameter.put(SessionParameter.ATOMPUB_URL, "http://localhost:8080/chemistry-opencmis-server-inmemory-0.2.0-incubating-SNAPSHOT/atom");
parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
parameter.put(SessionParameter.REPOSITORY_ID, "A1");

Session s = f.createSession(parameter);
Map pMap = new HashMap();
pMap.put("cmis:objectTypeId", "IITLib");
pMap.put("cmis:name", "MyDoc");
s.createDocument(pMap, s.createObjectId(s.getRepositoryInfo().getRootFolderId()), null, null, null, null, null));

When I ran this I got following exception.
org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException: Not Found

That says CmisObject type "IITLib" doesn't exist. But how come my client knows whether this type exist in repository where I am trying to post the document.

Well client know this by analyzing response received for the request http://localhost:8080/chemistry-opencmis-server-inmemory-0.2.0-incubating-SNAPSHOT/atom/A1/type?id=IITLib submitted to the repository.

Client generates this URL by investigating service document uritemplate of type typebyid. I have added a snippet below taken from service document of CMIS in-memory repository.

<cmisra:uritemplate>
<cmisra:template>http://localhost:8080/chemistry-opencmis-server-inmemory-0.2.0-incubating-SNAPSHOT/atom/A1/type?id={id}
</cmisra:template>
<cmisra:type>typebyid</cmisra:type>
<cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>
</cmisra:uritemplate>

Why this is called in-memory repository? No prize for guessing! once you restart your repository all your stored documents will be gone. So it's good for testing and not meant for production.

We still have to find out on how to extend CMIS data model.

Different repositories have different mechanism using which you can extend CMIS data model.

Lets try with in-memory Open-CMIS repository. All you have to do to register your extension is implement org.apache.chemistry.opencmis.inmemory.TypeCreator interface. class org.apache.chemistry.opencmis.inmemory.types.DefaultTypeSystemCreator.java can be used as an example. To register my extension I have added following snippet in DefaultTypeSystemCreator.java file

InMemoryDocumentTypeDefinition rootDocType = new InMemoryDocumentTypeDefinition("MyLib",
"My Type 1 Level 1",InMemoryDocumentTypeDefinition.getRootDocumentType());
Map<String, PropertyDefinition<?>> propertyDefinitions1 = new HashMap<String, PropertyDefinition<?>>();
PropertyDefinition<Boolean> prop_1 = PropertyCreationHelper.createBooleanDefinition("Is_BelongTo_Shiv_Lib",
"Sample Boolean Property");
propertyDefinitions1.put(prop_1.getId(), prop_1);
rootDocType.setPropertyDefinitions(propertyDefinitions1);
typesList.add(rootDocType);

build the in-memory repository war with changes and deploy it in your favorite servlet container. Lets try to execute our earlier code to create document

Session s = f.createSession(parameter);
Map pMap = new HashMap();
pMap.put("cmis:objectTypeId", "IITLib");
pMap.put("cmis:name", "MyDoc");
pMap.put("Is_BelongTo_Shiv_Lib", true);
s.createDocument(pMap, s.createObjectId(s.getRepositoryInfo().getRootFolderId()), null, null, null, null, null));

You should be able to see newly created document in repository.

Sunday, July 18, 2010

Exploring CMIS: Adding folder and document in alfresco using Http Client

This blog assumes that reader has basic understanding of CMIS. This blog organization is as follows: It starts with creating a folder structure in alfresco CMIS repository using apache client and atom pub binding of repository. Then we will use different discovery services to enquire our newly created folders. Hope you will have good time learning this.
Lets jump in....

First we will start with the code to create a folder name shiv_lib in alfresco. Find below the http client code and sample post xml used.

File input = new File("C:\\Users\\shivendra\\workspace\\ApacheClient\\src\\PostData.xml");
PostMethod post = new PostMethod("http://cmis.alfresco.com/service/cmis/p/children");
RequestEntity entity = new FileRequestEntity(input, "application/atom+xml; charset=ISO-8859-1");
post.setRequestEntity(entity);
HttpClient httpclient = new HttpClient();
httpclient.getState().setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("admin", "admin")
);
try {
int result = httpclient.executeMethod(post);
// Display status code
System.out.println("Response status code: " + result);
System.out.println(post.getResponseBodyAsString());
} finally {
post.releaseConnection();
}

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/"
xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/">
<title>Shiv_Lib</title>
<cmisra:object>
<cmis:properties>
<cmis:propertyId propertyDefinitionId="cmis:objectTypeId"><cmis:value>cmis:folder</cmis:value></cmis:propertyId>
</cmis:properties>
</cmisra:object>
</entry>

Notice the post method url(http://cmis.alfresco.com/service/cmis/p/children), since we haven't given any any path after p/{path} so this folder will be created on root folder. Newly created folder can be verified hitting http://cmis.alfresco.com/service/cmis/p/children in IE.

Now lets create some children folder inside this.All you have to do is change the post url and post xml as follows.

PostMethod post = new PostMethod("http://cmis.alfresco.com/service/cmis/p/Shiv_Lib/children");
<title>Meditation</title>
Hit http://cmis.alfresco.com/service/cmis/p/Shiv_Lib/children in IE and you will find out that Meditation folder is created inside Shiv_Lib.

Lets try putting some content in meditation folder. The only thing you have to take care here is cmis:objectTypeId will be cmis:document and the content need to added in document will go as base64 encoded and will be part of atom entry as follows.

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/"
xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/">
<title>Suggested Reading11</title>
<summary>Suggested Reading</summary>
<content type="text/plain">
MS4gR2l0YSAKIDIuIEthcm1heW9nYSBieSBWaXZla2FuYW5k
</content>
<cmisra:object>
<cmis:properties>
<cmis:propertyId propertyDefinitionId="cmis:objectTypeId"><cmis:value>cmis:document</cmis:value></cmis:propertyId>
</cmis:properties>
</cmisra:object>
</entry>


Since we want to create this in meditation folder so the URL will be: http://cmis.alfresco.com/service/cmis/p/Shiv_Lib/Meditation/children.

Once you run http client code with above changes, hit http://cmis.alfresco.com/service/cmis/p/shiv_lib/Meditation/children and you should be able to see document added. You can view content of document as plain text.

Next blog in this series I will cover CMIS query and discovery service.

Q and A

1. From where I get the AtomPub services URLs for alfresco.
The answer is alfresco list them at this http://cmis.alfresco.com/service/index/family/CMIS

Friday, June 11, 2010

An analysis on producer consumer problem

Producer consumer problem is classical problem solved by multi threading. Multi threading is needed only if we want to make the process efficient. e.g. A thread will start a machine to produce a design and then same thread will execute another machine which will use design produced by first machine to make product. No multi threading here, but this design is not efficient. We are not utilizing machines to their fullest capacity machine 1 is waiting while machine 2 is on work and vice versa.

Now lets modify the design: we can have two threads one will be executing machine 1 and another will execute machine 2. Both will run concurrently. While mc 1 is producing design mc 2 will make final product based on design earlier made by mc1.

class Store{

boolean empty = true;

}

class Producer extends Thread{

public void run(){

while(true){

if(Store.empty){

//pretend as if I am working though I am sleeping
sleep(1000);
Store.empty = false;
}}}}

class Consumer extends Thread{

public void run(){

while(true){
if(!Store.empty){

//I am working see below
sleep(2000);
Store.empty = true;

}}}}

The above technique is known as busy waiting. It has got serious problems e.g. It can consume all the available CPU time(since both thread will be always running and may not be really doing any productive work). Another problem can be if consumer thread priority is more then producer thread it may stop producer thread form producing anything.

To solve above we need to use monitors and wait state. Code added in above snippet to implement monitor/wait is highlighted.

class Store{
boolean empty = true;
}

class Producer extends Thread{

public void run(){

while(true){

syncronize(Store){

if(Store.empty){

//pretend as if I am working though I am sleeping
sleep(1000);
Store.empty = false;
Store.notifyAll();
Store.wait();
}}}}}

class Consumer extends Thread{

public void run(){

while(true){

syncronize(Store){
if(!Store.empty){

//I am working see below
sleep(2000);
Store.empty = true;
Store.notifyAll();
Store.wait();

}}}}

Sunday, May 16, 2010

Demystifying elementFormDefault

elementFormDefault attribute is useful when instead of mentioning form attribute to each element of schema we want to set form for all element to schema. In the schema below if we don't want to mention form attribute for each element we can use elementFormDefault="qualified".

<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="child" xmlns:tns="child"
<element name="EmpDetails">
<complexType>
<sequence>
<element name="fullname" form="qualified" type="string" />
<element name="name" form="qualified" type="string" />
</sequence>
</complexType>
</element>
</schema>

elementFormDefault becomes confusing when we start mixing namespace in schema. To make is simple lets start with some thumb rule.

1. Global Element(direct child of schema element) will always appear with name space in xml instance.

2. elementFormDefault is just a switch for local elements, if schema developer wants them to appear with namespace or without namespace in xml instance.

3. elementFormDefault attribute is applicable to only local elements of the schema in which it is defined and not to the local elements of imported schema.


Lets take one XML instance.

<tns:Emp xmlns:tns="parent" xmlns:tns1="child" >
<ID>ID</ID>
<tns1:EmpDetails>
<fullname>fullname</fullname>
</tns1:EmpDetails>
<EmpAddress>
<Street>Street</Street>
</EmpAddress>
</tns:Emp>

Lets take example of xml instance mentioned above and try to deduce schema "elementFormDefault" from this.

First thing to notice is, since instance has two namespace so one schema is importing another. From the first element we can say that in main schema elementFormDefault is unqulaified since instance doesn't has a default namespace and ID is local element defined in main schema. EmpDetails belongs to different namespace so its clear that EmpDetails exist as global element in the another schema. But what about elementFormDefault from default attribute of other schema. "fullname" which is local element in other schema and doesn't have any namespace, we can say that elementFromDefault in other schema is unqualified.

Now lets derive a possible schema from the above instance.

schema1

<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="parent"
xmlns:tns="parent" xmlns:child="child"
elementFormDefault="unqualified">
<import namespace="child" schemaLocation="NewXMLSchemaChild.xsd" />
<element name="Emp">
<complexType>
<sequence>
<element name="ID" type="string" />
<element ref="child:EmpDetails" />
<element name="EmpAddress" type="child:Address" />
</sequence>
</complexType>
</element>
</schema>

schema2

<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="child" xmlns:tns="child"
elementFormDefault="qualified">
<element name="EmpDetails">
<complexType>
<sequence>
<element name="fullname" type="string" />
</sequence>
</complexType>
</element>
<complexType name="Address">
<sequence>
<element name="Street" type="string" />
</sequence>
</complexType>
</schema>



XML instance mentioned below shows change in XML instance due to change in elementFormDefault attribute in schema1 and schema2

unqualified/qualified

<tns:Emp xmlns:tns="parent" xmlns:tns1="child" >
<ID>ID</ID>
<tns1:EmpDetails>
<tns1:fullname>tns1:fullname</tns1:fullname>
</tns1:EmpDetails>
<EmpAddress>
<tns1:Street>tns1:Street</tns1:Street>
</EmpAddress>
</tns:Emp>

qualified/unqualified

<tns:Emp xmlns:tns="parent" xmlns:tns1="child" >
<tns:ID>tns:ID</tns:ID>
<tns1:EmpDetails>
<fullname>fullname</fullname>
</tns1:EmpDetails>
<tns:EmpAddress>
<Street>Street</Street>
</tns:EmpAddress>
</tns:Emp>


qualified/qualified
<tns:Emp xmlns:tns="parent" xmlns:tns1="child" >
<tns:ID>tns:ID</tns:ID>
<tns1:EmpDetails>
<tns1:fullname>tns1:fullname</tns1:fullname>
</tns1:EmpDetails>
<tns:EmpAddress>
<tns1:Street>tns1:Street</tns1:Street>
</tns:EmpAddress>
</tns:Emp>


You can use below code to see if different instance are valid corresponding to respective schema.

import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

public class XMLValidator {
public static void main(String[] argv) throws Exception {
String schemaLang = "http://www.w3.org/2001/XMLSchema";
SchemaFactory factory = SchemaFactory.newInstance(schemaLang);
Schema schema = factory.newSchema(new StreamSource("NewXMLSchema.xsd"));
Validator validator = schema.newValidator();
validator.validate(new StreamSource("NewXMLSchema.xml"));
System.out.println("Validated Successfully");
}
}

Sunday, April 11, 2010

Adding a handler in AXIS2

AXIS2 handler is similar to servlet filter. AXIS2 handler gives you access to MessageContext similar to servlet filter which gives you access to request and response objects.

The typical use case of using AXIS2 handler are: adding security header in SOAPEnvelope, logging outgoing and incommming SOAPEnvelope. Lets take an example where I wan to add username as soap header in all the out going message from client.

You have to do following changes to engage handler.

AXIS2.xml

Since I want to add header in out going message so I will register my handler in outFlow phase of AXIS2. The mandatory attributes of handler tags are name and handler class name. Here I have created handler with the class name AXIS_Handler.

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


To qualify a class as a handler either we have to extend AbstractHandler or implement Handler interface.

public class AXIS_Handler extends AbstractHandler {

public InvocationResponse invoke(MessageContext ctx) throws AxisFault {

SOAPEnvelope env = ctx.getEnvelope();

SOAPHeader hdr = env.getHeader();

SOAPFactory factory = (SOAPFactory) env.getOMFactory();

OMNamespace ns = factory.createOMNamespace("http://ws.apache.org/axis2", "hns");

SOAPHeader head = factory.createSOAPHeader(env);

SOAPHeaderBlock header = head.addHeaderBlock("userID", ns);

header.setText("shiv");

return InvocationResponse.CONTINUE;
}

}

The next thing would be using modified axis2.xml file as configuartion context. There are two ways we can do.

ConfigurationContext cc= ConfigurationContextFactory.createConfigurationContextFromFileSystem(pathToRepository, pathToAxis2xml);

ServiceClient sc = new ServiceClient(cc, nulll, null, null);

But if you are not passing cc as parameter then you can pass as system property as JVM argument as follows.

-Daxis2.xml="location of axis2.xml file"

Once you are done with above. Run the client and you should able to see SOAPEnvelope containing header added by handler.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:axis="http://ws.apache.org/axis2">
<soapenv:Header><hns:userID xmlns:hns="http://ws.apache.org/axis2">shiv</hns:userID></soapenv:Header>
<soapenv:Body><axis:echoString><axis:param0>11</axis:param0></axis:echoString></soapenv:Body>
</soapenv:Envelope>

Tuesday, April 6, 2010

Adding SOAP header in axiom SOAPEnvelope

SAAJ api provides addheader method to add soap header but we don't have similer method in axiom SOAPEnvelope. I took me a while to figure out how to do that. Below is the peace of code to achieve this in axiom SOAPEnvelope.

Actually I was trying to implement handler where I got hold of SOAPEnvelope form messagecontext and wanted to add SOAPHeader.


SOAPEnvelope env = ctx.getEnvelope();

SOAPHeader hdr = env.getHeader();

SOAPFactory factory = (SOAPFactory) env.getOMFactory();

OMNamespace ns = factory.createOMNamespace("http://ws.apache.org/axis2", "hns");

SOAPHeader head = factory.createSOAPHeader(env);

SOAPHeaderBlock header = head.addHeaderBlock("userID", ns);

header.setText("shiv");

If you happen to get hold of SOAPEnvelope you will see the following is appended in SOAPHeader section.

<soapenv:Header>
<hns:userID xmlns:hns="http://ws.apache.org/axis2">shiv</hns:userID>
</soapenv:Header>

Monday, March 15, 2010

Invisible object and memory leak

It's been quite long time I am involved in java development but I have never heard about invisible objects. We mainly know about unreachable objects while going through garbage collection mechanism in java.

Invisible objects are quite different than unreachable objects in following respects:

1. unreachable objects are those objects which doesn't has any references to them but in case of invisible object they have strong references assoicated with them but thses refrences are not available to any thread stack, making object invisible to garbage collector.
2. unreachable objects are eligible for GC and normally don't cause memory leak, while invisible objects are not eligible for gorbage collection causing memory leak
3. invisible objects are result of efficient implemenation of JVM which don't nullify references if they are out of scope unless the method is thrown from thread stack upon execution.

Lets take one exampe to explain it more clearly

public void run(){

try{

MyOject o = new MyObect();//1
o.callMyMethod();

} catch (Exception e){}
//do lot of other time taking things
}

at line 1 we have created an object, ideally when thread will complete try block, reference "o" will go out of scope and should be removed from stack making MyObject unreachable so eligible for garbage collection. But an efficient jvm implementation will not do that, it will retain the reference "o" referring to MyObject unless run method is executed and thrown out of thread stack. Since reference "o" is not available to thread's stack so it's invisible to garbage collector.

The best way to avoid this situation is set the reference "o" explicitly null in try block once we are done with it.

Wednesday, March 10, 2010

Use of noLocal parameter while creating subscriber in JMS

Lets examine jms api for creating subscriber.

public TopicSubscriber createSubscriber(Topic topic, String messageSelector, boolean noLocal) throws JMSException

java doc says that third parameter is used to make a decision if subscriber want to consume message published by itself (if same connection is used to create publisher which publishes the message) or not.

Not very much clear! Lets design an experiment to see its behavior.

I will create one chat application with following details

topic: HowToEstablishPeaceInWorld

subscriber 1: Osama Bin Laden

subscriber 2: George Bush

This chat application will be based on JMS. Both these subscribers are publishers as well. One will type one's GREAT idea on one's console and it will be visible to other.

The pseudo code below shows how subscribers have subscribed the topic.

Topic chatTopic = (Topic)jndi.lookup("HowToEstablishPeaceInWorld");

TopicSubscriber OsamaBinLaden = subSession.createSubscriber(chatTopic);

TopicSubscriber GeorgeBush = subSession.createSubscriber(chatTopic);

This is Bush console
Bush: hi
Bush says: hi
osama says: hello

This is osama console

Bush says: hi
osama: hello
osama says: hello

The problem here is, the subscribers are consuming the message posted by themselves. Now lets modify the code and see the change in output

TopicSubscriber subscriber = subSession.createSubscriber(chatTopic,null,true);

This is Bush console
Bush: hi
osama says: hello

This is osama console
Bush says: hi
osama: hello

Hope you noticed the difference subscribers are no more consuming message posted by themselves(no more Bush says to Bush console).

Lets see how chat on world peace goes further.

Bush console

Bush: U still alive?

osama console

Bush says: U still alive?

Now osama thinks doesn't jms offers a way so that I don't see what Bush is typing but bush will see everything I type. He contacted software wing of al-Qaeda and they didn't let osama down.

The second argument in create Subscriber can be used to filter message.

Find below the source code for chat program. The code is in respect to jboss MQ server.


import javax.jms.*;
import javax.naming.*;
import java.io.*;
import java.io.InputStreamReader;
import java.util.Properties;

public class Chat implements javax.jms.MessageListener{
private TopicSession pubSession;
private TopicSession subSession;
private TopicPublisher publisher;
private TopicConnection connection;
private static String username;

/* Constructor. Establish JMS publisher and subscriber */
public Chat(String username)
throws Exception {
// Obtain a JNDI connection
Properties env = new Properties( );
// ... specify the JNDI properties specific to the vendor
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
env.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");



InitialContext jndi = new InitialContext(env);

// Look up a JMS connection factory
TopicConnectionFactory conFactory =
(TopicConnectionFactory)jndi.lookup("TopicConnectionFactory");

// Create a JMS connection
TopicConnection connection =
conFactory.createTopicConnection();

// Create two JMS session objects
TopicSession pubSession =
connection.createTopicSession(false,
Session.AUTO_ACKNOWLEDGE);
TopicSession subSession =
connection.createTopicSession(false,
Session.AUTO_ACKNOWLEDGE);

// Look up a JMS topic
Topic chatTopic = (Topic)jndi.lookup("topic/HowToEstablishPeaceInWorld");

// Create a JMS publisher and subscriber
TopicPublisher publisher =
pubSession.createPublisher(chatTopic);
TopicSubscriber subscriber =
subSession.createSubscriber(chatTopic,null,true);

// Register the jms message listener
subscriber.setMessageListener(this);

// Intialize the Chat application
set(connection, pubSession, subSession, publisher, username);

// Start the JMS connection; allows messages to be delivered
connection.start( );

}
/* Initialize the instance variables */
public void set(TopicConnection con, TopicSession pubSess,
TopicSession subSess, TopicPublisher pub,
String username) {
this.connection = con;
this.pubSession = pubSess;
this.subSession = subSess;
this.publisher = pub;
this.username = username;
}
/* Receive message from topic subscriber */
public void onMessage(Message message) {
try {
TextMessage textMessage = (TextMessage) message;
String text = textMessage.getText( );
System.out.println(text);
} catch (JMSException jmse){ jmse.printStackTrace( ); }
}
/* Create and send message using topic publisher */
protected void writeMessage(String text) throws JMSException {
TextMessage message = pubSession.createTextMessage( );
message.setText(username+" says: " +text);
publisher.publish(message);
}
/* Close the JMS connection */
public void close( ) throws JMSException {
connection.close( );
}
/* Run the Chat client */
public static void main(String [] args){
try{

Chat chat = new Chat(args[0]);

// Read from command line
BufferedReader commandLine = new
java.io.BufferedReader(new InputStreamReader(System.in));

// Loop until the word "exit" is typed
while(true){
String s = commandLine.readLine( );
if (s.equalsIgnoreCase("exit")){
chat.close( ); // close down connection
System.exit(0);// exit program
} else
chat.writeMessage(s);
}
} catch (Exception e){ e.printStackTrace( ); }
}
}

Tuesday, February 23, 2010

Generics and Polymorphism

List<Object> li = new ArrayList<Number>();//1

Why this will give compilation error? Number is sub class of Object, isn't this the way polymorphism works in java.

Let's investigate the problem raised if compiler allows it. If compiler accepts list of type object to refer list of any subclass of object then same will be true for adding any subtype of object to li, as mentioned below in line 2

li.add("SHIV"); //2


In essence, if compiler doesn't stop it at line 1 while assigning, it will never be in position to stop you from putting string into Number list. So correct way will be

List<Object> li = new ArrayLLIst<Object>();

i.e. List<T> li = new ArrayList<T>(); implies T in both side should be exactly same.

But this look like a serious restriction, how to get away with this(I mean how to achieve polymorphism in generics)? Java comes with wild card to solve these issue to some extent.

List<?> li = new ArrayList<Number>();//3
List<? extends Object> li = new ArrayList<Number>();//4
List<? super Boolean> li = new ArrayList<Number>();//5

In line 3 li can be assigned to ArrayList on any type, n line 4 li can be assigned to any type which extends object and line 5 can refer to any type super class of Boolean. It's evident from the above examples that wild card (?) get us polymorphism in case of generics. But polymorphism in generics comes with some restrictions. Let's discuss them.
List<?> li = new ArrayList<Number>();

li can be assigned to any type but nothing can be added to li. Because compiler will be aware of only reference type, and that is wild card(not a type).

List <? extends Number> li= new ArrayList<Boolean>();

Here li can be used to refer any object that extends Number. What about adding objects to li? Think carefully and answer. If your answer is any object extends Number can be added, then you are wrong. Actually you cannot add object of any type to li. Because here again compiler doesn't know which type exactly li is referring to. Without the restriction you may end up creating list of Boolean and add Number to it.

List <? super Number> li = new ArrayList<Number>();
What about this, as you might have guessed that li can refer to Number or any super class of it. But the big deal will always be about adding element to li. Good news is that, this is only combination with wild card where elements can be added. Compiler is sure that type of li will be either Number or any super class of Number. So if you add Number or sub class of it, it's perfectly fine.

Lets summarize it....


What li can refer to
What can be added to li

List<T> li = new ArrayList<T> ()
li can refer only ArryList of type T T or any sub class of T can be added to li

List<?> li = new ArrayList<T> ()
li can refer any type Nothing can be added to li

List<? extends T> li = new ArrayList<T> ()
li can refer ArrayList of type T or any sub type of T Nothing can be added to li

List<? super T> li = new ArryList<T>()
li can refer ArrayList of type T or any supertype of T T or any sub type of T can be added to li

Tuesday, February 2, 2010

A Date with java.util.Date

Recently I encountered with interesting problem where I wanted to change java.util.Date from one time zone to other. It shouldn't be surprising that its not possible! why ? carry on reading.

When we instantiate Date it's instantiated as System.currentTimeMillis() from the OS. That represents time in mills from a reference date. But then things gets confusing when we try to print this. Lets do one experiment, run same code with different zone selected from your computer.

Date d = new Date();
System.out.println("date "+d);

This will print different sting for same date. This is because toString() implementation of Date takes default time zone of computer to print time zone. If it doesn't find any then it will get GMT time for the date instance.

What to do if we want to display date in time zone other than JVM/OS. We know that Date cannot be used to do that.
What the code below doing?

Date d = new Date();
Calendar c = Calendar.getInstance();
c.setTime(d);
c.setZome(TimeZone.getTimeZone("IST"));
d = c.getTime();

I guess you answered nothing. That's correct, the whole point is Date doesn't store time zone information. But question about displaying Date in zone other than JVM remains unanswered. Let's answer it.

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setZome(TimeZone.getTimeZone("IST"));
String IST_Date = df.format(d);
System.out.println("DATE if IST zone "+IST_Date);

Now what if I want to create Date instance from IST_Date string.

Date d = df.parse(IST_Date);

Tuesday, January 26, 2010

Adapter Pattern

Adapter change the interface of a class to make is usable by client. Lets take a real world example....

Railways has got an interface to get the reservation details. Ex




A website which is doing well in ticket booking for flights want to introduce rail ticket booking as well. Since they are in business from long time, they have already got there generic interface in place for flight reservation.



My website TicketReservation class can't talk directly to RailReservation class. To make it happen we need some class which delegates all the calls make to isTicketAvalable to isRailTicketAvailable.



RailTicketAdapter is inherited form the client interface and composing RailTicketReservationImpl.

Saturday, January 16, 2010

Factory patterns: A Quick Look

Factory patterns are mainly used to encapsulate creation of concrete object. These pattern facilitates adhering to design principle like: Inversion of control (Depend upon abstractions, Do not depend on concrete class), Program to interface not to implementation.

Simple factory: Suppose we want to create different concrete class based on different condition for ex.

class SellTicket {

Ticket t= new TicketCreationFactory().create("Bus");
t.sell();

}

class TicketCreationFactory {

public Ticket create(String type){

if(type.equals("Bus") return new BusTicket();
if(type.equals("Train") return new TrainTicket();

}
}

The advantage of having separate factory class would be reusability and maintainability. Different classes can use factory to create Tickets and we have got only one pace to modify for any change in object creation logic. But still we are violating some important design principle for ex. "Close for modification but open for extension"(to change object creation logic we have to modify factory class).

Factory method pattern: Factory method pattern provide an interface with abstract method to create object. By doing this it forces sub class to decide which class to instantiate. (Don't create instance in your interface delegate it to implementation)

abstract class SellTicket {

Ticket t = createTicket(String type) ;
t.sell();
public abstract Ticket createTicket(String type);

}

class sellTicketImpl extends SellTicket{

Ticket t = creatTicket() ;
t.sell();
public Ticket createTicket(String type){
if(type.equals("Bus")){
new BusTicket();
}
}

}

To have another object creation logic we can have another subclass of SellTicket.
Another interesting observation is our high level class SellTicket is not dependent on low level class ticket, instead it's dependent on abstract class Ticket. That's what know as "inversion of control" (Depend on abstraction, not on the concrete class). Lets explore it further, suppose we don't use abstract factory method
Ticket t = new BusTicket(); or Ticket t = new TrainTicket();
Though we have abstract class Ticket but our high level class is dependent on concrete implementation to create instance of class. By using factory method pattern we don't have to bother about change in class to be created or unknown classes to be added in future, because we have written our code that used interface not implementation.

Abstract Factory Pattern: Provides a interface for creating family of related objects without specify there concrete class.

Abstract factory pattern uses factory method pattern to create individual objects.

public interface TravelKitFactory{

public Ticket CreateTicket();
public WinterKit CreateWinterKit();

}

Wednesday, January 13, 2010

Singleton pattern

Implies having at most single instance of a class.

Need:Singleton provides global way to access resources. Suppose we have a centralize configuration data to be used across the application, more than one instance of configuration data will result in incorrect behaviour of application. There are other examples as well when we need singleton mainly, thread pools, caches etc.

Ways to create:

class IAmSingleton{

private static IAmSingleton singletonRef;
public static IAmSingleton getInstance(){
if(singletonRef ==null)
return singletonRef = new IAmSingleton(); //line 1
else
return singletonRef ;
}
private IAmSingleton(){}
}

What if two threads are at line 1, two instances will be created. To stop this lets syncronize getInstance().
Synchronization come with cost of performance loss. Lets see how can we achieve single instance in multi threading environment with less impact.

If the object desired to behave as singleton is less resource incentive, we can go for pre loading the class(instance of class will be created at the class loading time).

class IAmSingleton{
private static IAmSingleton singletonRef = new IAmSingleton();
private IAmSingleton(){}
}

But if its resource incentive we can try to improve our synchronization logic. Lets see how..

class IAmSingleton{

private static volatile IAmSingleton singletonRef ;
public static IAmSingleton getInstance(){
if (singletonRef ==nulll)
syncronize (IAmSingleton.class){
if (singletonRef == null)
return new IAmSingleton();
else
return singletonRef ;
}
}
else
return singletonRef ;
}
privateIAmSingleton(){}

}

The advantage the above code will provide is, synchronized block will not be executed once value is assigned to singleton ref. This strategy is known as double check locking(double check locking doesn't work pre 1.5 JDK).

Sunday, January 10, 2010

Decorate your skills with Decorator pattern

To understand this pattern lets take a case.

Suppose a multiplex has a application to sell tickets. Now they want to sell tickets with different food/beverage option. We will try different design option one by one.

Option 1.
We sub class the base class and override the cost method. But that will result in class explosion(having lot of sub classes for each new functionality).
class MovieTicketPrice {

public double getTicketPrice(){

}
}

class MovieTicketWithCoke extends MovieTicketPrice {

public Double getTicketPrice(){
//modify the base class implementation here
}
}

but problem is we will have tons of subclasses(MovieTicketWithPopcorn, MovieTicketWithCokeAndPopcorn) of MovieTicketPrice corresponding to different options available.

Option 2.

We can have a single class and modify it

class MovieTicketPrice {
public double getTicketPrice(){}
public double addCokeSercharge(){}

}

But this design is violating basic design principle "Open for extension closed for modification". Its never a good idea to modify your already tested code to add new features.

Now lets see what we can achieve using decorator(wrapper ) pattern.

class MovieTicket{

public double getTicketPrice(){}

}

class DecoratePriceWithCoke extends MovieTicket{

MovieTicketPrice t ;
public double getTicketPrice(){
return t.getTicketPrice() + 50;
}
}

class DecoratePriceWithPopCorn extends MovieTicket{

MovieTicketPrice t ;
public double getTicketPrice(){
return t.getTicketPrice() + 80;
}
}

Now suppose we want to have an option of ticket with popcorn and coke, we don't need another class...just decorate(wrap) your movie ticket with coke and popcorn.

MovieTicket t = new MovieTicket();
t = DecoratePriceWithCoke(t);
t = DecoratePriceWithPopCorn(t);

To summerize you have to create a decorator class for new option and that can be mixed with other available option. for ex.. suppose multiplex introduce ticket with pizza. Then programmer just has to create pizza decorator class and the same can be mixed with options like pizza with coke without creating a new class PizzaWithCoke.