Using DynaCache as Cache Implementation in Hibernate

Hibernate makes it very easy for us to use caching framework of our own choice. Now if you know the application that your developing is going to be deployed in WebSphere Application Server, then you might want to use the DynaCache caching framework which ships with IBM WebSphere Application Server. I wanted to try that so i did create this sample application that talks to database using Hibernate and makes use of DynaCache for caching. You can download the sample application from here In order to ask Hibernate to use DynaCache as caching implementation first thing that you will have to do is create a class that implements org.hibernate.cache.CacheProvider interface, this interface gets invoked whenever Hibernate wants to initialize cache for particular region.

package com.webspherenotes.hibernate.cache;

import java.util.Date;
import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.hibernate.cache.Cache;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.CacheProvider;

import com.ibm.websphere.cache.DistributedMap;

public class DynaCacheProvider implements CacheProvider {

  public DynaCacheProvider() throws NamingException {
    System.out.println("Entering DynaCacheProvider() constructor");

  }

  public Cache buildCache(String regionName, Properties properties)
      throws CacheException {
    System.out.println("Inside DynaCacheProvider.buildCache " + regionName);
    
    String cacheInstanceJNDIName =(String) properties.get(regionName);
    
    if(cacheInstanceJNDIName == null){
      cacheInstanceJNDIName = (String) properties.get("dynacache.default.cacheinstancename");
      if(cacheInstanceJNDIName == null){
        cacheInstanceJNDIName = "services/cache/distributedmap";
      }  
    }
    System.out.println("Cache instance JNDI name " + cacheInstanceJNDIName);
    DistributedMap distributedMap;
    DynaCache cache = null;
    try {
      InitialContext ic = new InitialContext();
      distributedMap = (DistributedMap) ic.lookup(cacheInstanceJNDIName);
      System.out.println("DistributedMap found in JNDI " + distributedMap);
      cache = new DynaCache(distributedMap, regionName);
    } catch (NamingException e) {
      e.printStackTrace(System.out);
    }


    return cache;
  }

  public boolean isMinimalPutsEnabledByDefault() {
    return false;
  }

  public long nextTimestamp() {
    return new Date().getTime();
  }

  public void start(Properties properties) throws CacheException {
  }

  public void stop() {
  }

}
,. The buildCache method is responsible for returning object of class implementing org.hibernate.cache.Cache interface that should be used for caching objects for this region. In my case i want to have granular control on which DynaCache instance should be used to store the cached object. The rule goes like this
  1. First check if there is region specific instance, if yes use that
  2. If there is no region specific instance check the value of dynacache.default.cacheinstancename to see if that's set if yes use it.
  3. The last option is to use services/cache/distributedmap which is name of the default cache instance in WAS
Next i had to create DynaCache class that implements org.hibernate.cache.Cache, the object of this class gets control for getting, setting, removing entries from cache. I am actually calling methods on DistributedMap

package com.webspherenotes.hibernate.cache;

import java.util.Map;

import org.hibernate.cache.Cache;
import org.hibernate.cache.CacheException;

import com.ibm.websphere.cache.DistributedMap;

public class DynaCache implements Cache {

  private DistributedMap map;
  private String regionName;

  public DynaCache(DistributedMap map, String regionName) {
    System.out.println("Creating object of HibernateCache() " + regionName);
    this.map = map;
    this.regionName = regionName;
  }

  public void clear() throws CacheException {
    map.clear();
  }

  public Object get(Object key) throws CacheException {
    System.out.println("Inside HibernateCache.get " + key);
    return map.get(getMapKey(key));
  }

  public String getRegionName() {
    System.out.println("Inside HibernateCache.getRegionName " + regionName);

    return regionName;
  }

  public void put(Object key, Object value) throws CacheException {
    System.out.println("Inside HibernateCache.put " + key + " " + value);
    System.out.println(value.getClass().getName());
    map.put(getMapKey(key), value);
  }

  public Object read(Object key) throws CacheException {
    System.out.println("Inside HibernateCache.read " + key);

    return map.get(getMapKey(key));
  }

  public void remove(Object key) throws CacheException {
    map.remove(getMapKey(key));
  }

  public void update(Object key, Object value) throws CacheException {
    map.put(getMapKey(key), value);
  }

  private String getMapKey(Object key) {
    return regionName + "." + key;
  }

  @Override
  public void destroy() throws CacheException {

  }

  @Override
  public long getElementCountInMemory() {
    return this.map.size();
  }

  @Override
  public long getElementCountOnDisk() {
    return 0;
  }

  @Override
  public long getSizeInMemory() {
    return 0;
  }

  @Override
  public int getTimeout() {
    return 0;
  }

  @Override
  public void lock(Object arg0) throws CacheException {

  }

  @Override
  public long nextTimestamp() {
    return 0;
  }

  @Override
  public Map toMap() {
    return this.map;
  }

  @Override
  public void unlock(Object arg0) throws CacheException {

  }

}
Last thing is to define the com.webspherenotes.hibernate.cache.DynaCacheProvider as cacheProvider in hibernate.cfg.xml this tells the Hibernate framework to use the DynaCacheProvider that we just created.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
        <property name="connection.url">jdbc:derby://localhost:1527/C:/data1/contact</property>
        <property name="connection.username">dbadmin</property>
        <property name="connection.password">dbadmin</property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.DerbyDialect</property>

      
       <property name="cache.provider_class">com.webspherenotes.hibernate.cache.DynaCacheProvider</property>
       <property name="dynacache.default.cacheinstancename">services/cache/distributedmap</property>
       <property name="com.javaworld.memcache.Contact">services/cache/contact</property>
       
       <property name="hibernate.cache.use_second_level_cache">true</property>
       
         <property name="cache.use_query_cache">true</property>
       <property name="">localhost:11211</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup 
        <property name="hbm2ddl.auto">create</property>-->

        <mapping resource="com/javaworld/memcache/Contact.hbm.xml"/>
    <mapping resource="com/javaworld/memcache/Address.hbm.xml"/>
    </session-factory>

</hibernate-configuration>
In this file i am telling hibernate to use service/cache/contact cache instance for caching Contact object but the Address objects would get stored in the default cache. So after deploying the code i did hit the cache few times and this what i see in the cachemonitor

Making asynchronous call to REST service

In the Using javax.xml.ws.Dispatch for REST Client entry i talked about how you can use the javax.xml.ws.Dispatch class for making call to the REST service. As you can see it makes calling the REST service difficult and it might not make sense to use this approach for calling service in most cases but it might be good idea to think about this approach when you want to make asynchronous calls, i wanted to try this approach so i made following changes to the DispatcherTest1.java

package com.webspherenotes.jaxrs;

import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;

public class DispatcherTest1 {

  public static void main(String[] args) {
    try {
      QName serviceName = new QName("http://www.webspherenotes.com/rest", "svc");
      QName portName = new QName("http://www.webspherenotes.com/rest", "port");
      Service svc = Service.create(serviceName);
      svc.addPort(portName, HTTPBinding.HTTP_BINDING, 
   "http://localhost:9080/MyWebService/rest/contact/1");
      Dispatch dis =
        svc.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);
      Map requestContext = dis.getRequestContext();
      requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "GET");
      
      Future f= dis.invokeAsync(null, new DemoAyncHandler());
      System.out.println("After making async call to request");
      f.get();
    
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

  }

}
We have to change only couple of lines here, first change the Dispatcher method that your calling from invoke to invokeAsync. The invokeAsync method returns object of java.util.concurrent.Future, calls its get method so that the current thread does not end before it gets calls response callback. Then create DemoAsyncHandler class that gets called when the response for REST service is ready.


package com.test;

import java.util.concurrent.ExecutionException;

import javax.xml.transform.Source;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;

public class DemoAyncHandler implements AsyncHandler{

  @Override
  public void handleResponse(Response response) {
    try {
      System.out.println("Inside DemoAsyncHandler.handleResponse "
   + response);
      Source source = response.get();
      XMLHelper.prettyPrintXML(source, System.out);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

}
Only thing that i am doing in the DemoAsyncHandler is to print the response on console, this is how the output looks like

Pretty print XML document

I use the following XMLHelper.java code whenever i have a requirement to pretty print XML, it can handle String, Document and Source, the common objects that i need to print


package com.webspherenotes.xml;

import java.io.OutputStream;
import java.io.StringReader;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;

public class XMLHelper {

  public static void prettyPrintXML(Source source, OutputStream stream) {
    try {
      Transformer transformer = TransformerFactory.newInstance()
          .newTransformer();
      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
      transformer.
   setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
      transformer.transform(source, new StreamResult(stream));
    } catch (Exception e) {
      e.printStackTrace(System.out);
    }
  }
  
  public static void prettyPrintXML(Document doc, OutputStream stream) {
    prettyPrintXML(new DOMSource(doc),stream);
  }
  
  public static void prettyPrintXML(String xmlString, OutputStream stream){
    prettyPrintXML(new StreamSource(new StringReader(xmlString)),stream);
  }
}

Using javax.xml.ws.Dispatch for REST Client

The JAX-WS has a javax.xml.ws.Dispatch class that you can use for making HTTP call, So i can use it even for making call to REST service and i wanted to see how that works. I do have a Contact REST service that allows me to make CRUD calls on the Contact table, For example i can call http://localhost:9080/MyWebService/rest/contact/1 URL to get a record from CONTACT table where contact Id is 1. This is the output i get when i call it for contactId 1
The REST service returns CONTACT object in XML format for contactId equal to 1, I wanted to try making the same call using the javax.xml.ws.Dispatch object, this is the code that i built for it.

package com.webspherenotes.rest;

import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;

public class DispatcherTest1 {

  public static void main(String[] args) {
    QName serviceName = new QName("http://www.webspherenotes.com/rest", "svc");
      QName portName = new QName("http://www.webspherenotes.com/rest", "port");
      Service svc = Service.create(serviceName);
      svc.addPort(portName, HTTPBinding.HTTP_BINDING,
   "http://localhost:9080/MyWebService/rest/contact/1");
      Dispatch dis =
        svc.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);
      Map requestContext = dis.getRequestContext();
      requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "GET");
      Source responseSource = dis.invoke(null);
     XMLHelper.prettyPrintXML(responseSource, System.out);
  }
}
In this class first i am creating a Service object pointing to http://localhost:9080/MyWebService/rest/contact/1 URL and then i am getting the Dispatcher object pointing to it. Next i use the RequestContext object to set the HTTP request method to GET and then i call the Dispatcher.invoke() which actually makes HTTP request and it returns Source object representing the response. Once i have the response i am uing the XMLHelper.prettyPrintXML() for pretty printing the XML, this is how the output looks like

Returning a binary file from REST service

You might want to return a binary file such as image or pdf from a REST service, if thats the case then JAX-RS provides you with 3 options. I wanted to try those options to i did create a sample application, that you can download from here. I did create a HelloBinaryService.java file which is a resource class that has 3 methods in each of these methods i am reading a static image file from c:/temp and returning it

package com.webspherenotes.rest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.StreamingOutput;

@Path("/hellobinary")
public class HelloBinaryService {

  @GET
  @Path("/file")
  @Produces("image/png")
  public File getFile(){
    File samplePDF = new File("c:/temp/distributedmap.png");
    return samplePDF;
  }

  @GET
  @Path("/fileis")
  @Produces("image/png")
  public InputStream getFileInputStream()throws Exception{
    FileInputStream fileIs = new FileInputStream("c:/temp/distributedmap.png");
    return fileIs;
  }

  @GET
  @Path("/fileso")
  @Produces("image/png")
  public StreamingOutput getFileStreamingOutput() throws Exception{
    
    return new StreamingOutput() {
      
      @Override
      public void write(OutputStream outputStream) throws IOException,
          WebApplicationException {
        FileInputStream inputStream = new FileInputStream("c:/temp/distributedmap.png");
        int nextByte = 0;
        while((nextByte  = inputStream.read()) != -1 ){
          outputStream.write(nextByte);
        }
        outputStream.flush();
        outputStream.close();
        inputStream.close();
      }
    };
  }
  
}
The first and easiest option would be to return a object of java.io.File directly and the JAX-RS will figure out how to read the file and return binary content of the file, but you cannot use this option if your returning a file that is not stored on the file system. Second option would be to return object of InputStream, in that case the InputStream could be pointing to file on local system or file stored in database or something like that, in this case JAX-RS container will figure out how to return bytes from InputStream and return it The last option would be to return object of StreamingOutput, this gives you most flexibility in this case JAX-RS container will give you control at the time of writing body of the message, this is little more work for you since you have to take care of reading the bytes from InputStream and write into output stream but then you get chance to compress the content,....

Createing Hello JAXRS service for deployment using Sun Jersey

If you want to build a REST service and deploy it in one of the Java EE 5 compliant containers for example WebSphere APplication Server 7.0, then you will have to use one of the external JAXRS containers such as Jersey, which is very popular among REST service developers.

I wanted to try this option out so i built a HelloJersey application that you can download from here. I followed these steps for building my sample application

  • First create a Dynamic Web APplication project called HelloJersey

  • Download following .jar files and add it to the WEB-INF/lib folder of your web application

    1. asm-3.1.jar

    2. jersey-core-1.5.jar

    3. jersey-server-1.5.jar

    4. jsr311-api-1.1.1.jar




  • Next create a HelloJerseyRESTService.java file like this

    package com.webspherenotes.rest;

    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.QueryParam;
    import javax.ws.rs.core.MediaType;

    @Path("/hellojersey")
    public class HelloJerseyRESTService {

    @GET
    @Produces(MediaType.TEXT_HTML)
    public String sayHello(@QueryParam("name") String name ){
    return "Hello " + name;
    }
    }

    The HelloJerseyRESTService only handles GET request and returns HTML markup


  • Next declare the Jersey servlet in the web.xml and create servlet mapping

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>DynaCacheSample1</display-name>
    <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>com.webspherenotes.rest</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    </web-app>



  • After you deploy the application in container you should see that when the server is starting it will scan all the resource and in our case it should find only com.webspherenotes.rest.HelloJerseyRESTService

    [10/16/11 17:17:47:250 PDT] 0000000e ApplicationMg I WSVR0228I: User initiated module stop operation request completed on Module, HelloJersey.war, of application, DynaCacheSample1EAR
    [10/16/11 17:17:49:932 PDT] 0000000e ApplicationMg I WSVR0225I: User initiated module start operation requested on Module, HelloJersey.war, of application, DynaCacheSample1EAR
    [10/16/11 17:17:50:466 PDT] 0000000e webapp I com.ibm.ws.webcontainer.webapp.WebGroupImpl WebGroup SRVE0169I: Loading Web Module: HelloJersey.
    [10/16/11 17:17:50:521 PDT] 0000000e WASSessionCor I SessionContextRegistry getSessionContext SESN0176I: Will create a new session context for application key default_host/HelloJersey

    [10/16/11 17:17:50:602 PDT] 0000000e PackagesResou I Scanning for root resource and provider classes in the packages:
    com.webspherenotes.rest
    [10/16/11 17:17:50:666 PDT] 0000000e ScanningResou I Root resource classes found:
    class com.webspherenotes.rest.HelloJerseyRESTService

    [10/16/11 17:17:50:667 PDT] 0000000e ScanningResou I No provider classes found.
    [10/16/11 17:17:50:850 PDT] 0000000e WebApplicatio I Initiating Jersey application, version 'Jersey: 1.5 01/14/2011 12:36 PM'
    [10/16/11 17:17:51:816 PDT] 0000000e servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [DynaCacheSample1EAR] [/HelloJersey] [Jersey REST Service]: Initialization successful.
    [10/16/11 17:17:51:817 PDT] 0000000e webcontainer I com.ibm.ws.wswebcontainer.VirtualHost addWebApplication SRVE0250I: Web Module HelloJersey has been bound to default_host[*:9080,*:80,*:9443,*:5060,*:5061,*:443].
    [10/16/11 17:17:51:824 PDT] 0000000e ApplicationMg I WSVR0226I: User initiated module start operation request completed on Module, HelloJersey.war, of application, DynaCacheSample1EAR
    [10/16/11 17:17:51:825 PDT] 0000000e AppBinaryProc I ADMA7021I: Distribution of application DynaCacheSample1EAR completed successfully.




You can test the service by either directly going to the http://localhost:9080/HelloJersey/rest/hellojersey?name=sunil URL or using the REST client

Create Hello JAX-RS service in WAS 8.0

The WAS 8.0 is Java EE 6.0 compliant that means it allows you to deploy JAX-RS compliant service and you dont have to go through painful steps for setting up external JAXRS container such as Jersey in your web application

I wanted to figure out what it takes to create HelloREST application in WAS 8.0 so i followed this steps to create Hello JAX-RS service. You can download the source code for sample from here


  • First i used RAD 8.0 to create Servlet Technology 3.0 compliant web application( Which means no need for web.xml or no need of declaring servlets)


  • Next create a HelloRestService class that is basically a REST service and is available at /hellorest url


    package com.webspherenotes.rest;

    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.QueryParam;

    @Path("/hellorest")
    public class HelloRESTService {

    @GET
    @Produces("text/html")
    public String sayHello(@QueryParam("name") String name){
    return "Hello " + name;
    }

    }




  • Next create HelloApplication class which is basically a REST servlet class like this.

    package com.webspherenotes.rest;

    import java.util.HashSet;
    import java.util.Set;

    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;

    @ApplicationPath("/rest/")
    public class HelloApplication extends Application{

    @Override
    public Set<Class<?>> getClasses() {
    Set<Class<?>> s = new HashSet<Class<?>>();
    s.add(HelloRESTService.class);
    return s;
    }

    }

    The HelloApplication class extends javax.ws.rs.core.Application which helps you to declare the JAX-RS application, in this class i am overriding the getClasses() method which returns set of JAX-RS classes that act as JAX-RS service. In my case i do have only one HelloRESTService class so i am only adding that

  • Now deploy the application on your WAS 8.0 server, if you try accessing it by sending GET request to http://localhost:9080/HelloRESTService/rest/hellorest?name=Sunil URL and you should get Hello Sunil as response

Pretty printing SOAP messages

If your dealing with SAAJ API or you want to create a Debug Message Handler that prints the SOAP Message then you can call SOAPmessage.writeTo(System.out), but this method writes the full SOAP message in one line and which can be little hard to read this is sample output


<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><wn:sayHello SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wn="http://ws.websphrenotes.com/"><arg0>Sunil</arg0></wn:sayHello></SOAP-ENV:Body></SOAP-ENV:Envelope>


If you want to pretty print the SOAPMessage then you can use the following method.


package com.webspherenotes.ws;
import java.io.ByteArrayOutputStream;

import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
public class SOAPHelper {
public static String getSOAPMessageAsString(SOAPMessage soapMessage) {
try {

TransformerFactory tff = TransformerFactory.newInstance();
Transformer tf = tff.newTransformer();

// Set formatting

tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",
"2");

Source sc = soapMessage.getSOAPPart().getContent();

ByteArrayOutputStream streamOut = new ByteArrayOutputStream();
StreamResult result = new StreamResult(streamOut);
tf.transform(sc, result);

String strMessage = streamOut.toString();
return strMessage;
} catch (Exception e) {
System.out.println("Exception in getSOAPMessageAsString "
+ e.getMessage());
return null;
}

}
}


It generates the output which looks like this

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<wn:sayHello SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wn="http://ws.websphrenotes.com/">
<arg0>Sunil</arg0>
</wn:sayHello>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>



I ended up doing this because i could not find SaajOutputer.java class

Updating WAS 8

In the Installing WAS 8 Beta on your machine, entry i talked about how IBM has changed the way we installed WebSphere Application Server starting from V8.0. Now we have to use the IBM Installation Manager,

One advantage of using the IBM Installation manager for installing/managing the WAS 8.0 is that updating it has become very easy, I had to use simple wizard to install latest WAS 8.0 recommended fixes on my machine, no need to go through the process of finding recommended fixes, downloading them and the using update installer to install fixes.








Installing enterprise application files by adding them to a monitored directory

The WebSphere Application Server 8.0 introduces this new feature, in which you can copy enterprise application file in the monitoredDirectory and it automatically gets installed on the server. This feature is similar to concept of copying .war file in the webapps directory. I wanted to try this feature, so i followed these steps

  • The monitored directory feature is disabled by default so the first step would be to enable this feature, for that login into WAS Admin Console and go to Applications -> Global Deployment settings.


    On this page the Monitor directory to automatically deploy applications check box is unchecked by default, so check it. Then you can either use the default path for the monitored directory which is app_profile_root/monitoredDeployableApps or you can change this path to something else, save the changes and restart the server

  • Once the server is restarted you will notice that app_profile_root/monitoredDeployableApps gets created for you


  • I did export HelloMonitoredDirectoryEAR.ear into the monitoredDirectory


  • After copying the .ear into monitoredDirectory i was looking at the logs and i could notice that it is being picked up for deployment

    [7/5/11 12:32:35:944 PDT] 00000013 WatchService I CWLDD0007I: Event id 1937700630-1. Start of processing. Event type: Added, File path: C:\IBM\WebSphere\AppServer\profiles\AppSrv01\monitoredDeployableApps\servers\server1\HelloMonitoredDirectoryEAR.ear.
    [7/5/11 12:32:36:022 PDT] 00000013 ModelMgr I WSVR0801I: Initializing all server configuration models
    [7/5/11 12:32:37:303 PDT] 00000013 WorkSpaceMana A WKSP0500I: Workspace configuration consistency check is disabled.
    [7/5/11 12:32:38:475 PDT] 00000013 AppManagement I CWLDD0028I: Event id 1937700630-1. The target of the current operation is [WebSphere:cell=ascendan-ggbz6iNode01Cell,node=ascendan-ggbz6iNode01,server=server1].
    [7/5/11 12:32:38:553 PDT] 00000013 AppManagement I CWLDD0014I: Event id 1937700630-1. Installing application HelloMonitoredDirectoryEAR...
    [7/5/11 12:32:40:022 PDT] 00000013 annotations I ArchiveInputStreamData mapData Collision on [ WEB-INF/classes/com/webspherenotes/test/HelloMonitoredServlet.class ] in [ HelloMonitoredDirectory.war ]
    [7/5/11 12:32:43:631 PDT] 00000014 annotations I ArchiveInputStreamData mapData Collision on [ WEB-INF/classes/com/webspherenotes/test/HelloMonitoredServlet.class ] in [ HelloMonitoredDirectory.war ]
    [7/5/11 12:32:55:645 PDT] 00000014 webcontainer I com.ibm.ws.webcontainer.internal.WebContainer addExtensionFactory SRVE0239I: Extension Factory [class com.ibm.ws.soa.sca.web.extension.SCAWebExtensionFactory] was registered successfully.
    [7/5/11 12:32:55:676 PDT] 00000014 webcontainer I com.ibm.ws.webcontainer.internal.WebContainer addExtensionFactory SRVE0240I: Extension Factory [class com.ibm.ws.soa.sca.web.extension.SCAWebExtensionFactory] has been associated with patterns [""].
    [7/5/11 12:32:55:692 PDT] 00000014 WebSphereSCAS I Added Servlet mapping: /dojo
    [7/5/11 12:32:55:692 PDT] 00000014 WebSphereSCAS I Added Servlet mapping: /dojo
    [7/5/11 12:32:55:692 PDT] 00000014 WebSphereSCAS I Added Servlet mapping: /tuscany
    [7/5/11 12:32:55:692 PDT] 00000014 WebSphereSCAS I Added Servlet mapping: /tuscany
    [7/5/11 12:32:58:848 PDT] 00000014 annotations I ArchiveInputStreamData mapData Collision on [ WEB-INF/classes/com/webspherenotes/test/HelloMonitoredServlet.class ] in [ HelloMonitoredDirectory.war ]
    [7/5/11 12:32:58:957 PDT] 00000014 InstallSchedu I ADMA5013I: Application HelloMonitoredDirectoryEAR installed successfully.
    [7/5/11 12:33:03:223 PDT] 00000013 annotations I ArchiveInputStreamData mapData Collision on [ WEB-INF/classes/com/webspherenotes/test/HelloMonitoredServlet.class ] in [ HelloMonitoredDirectory.war ]
    [7/5/11 12:33:04:144 PDT] 00000013 annotations I ArchiveInputStreamData mapData Collision on [ WEB-INF/classes/com/webspherenotes/test/HelloMonitoredServlet.class ] in [ HelloMonitoredDirectory.war ]
    [7/5/11 12:33:04:207 PDT] 00000013 annotations E CWWAM0001E: An exception occurred during annotation processing: java.lang.IllegalArgumentException: The feature 'annotated-classes' is not a valid feature

  • I did wait for couple of minutes and then i checked the WAS Admin console and i could see newly installed application like this



  • I wanted to see where exactly the application is getting installed so i looked at the value of application binaries and i can see that it got installed in regular installedApp directory