Showing posts with label buildscript. Show all posts
Showing posts with label buildscript. Show all posts

Automating portlet deployment on WebSphere Portal using Apache Maven

If you download sample code from my blog you will notice that i use Apache Maven as build tool, my source code is structured in Maven format and you will find a pom.xml file which is maven build script.

I like to make my development environment as simple as possible and automate deployment so that i can test my changes rapidly. So i did create this very basic approach for automating deployment of portlet to WebSphere Portal using xmlaccess + maven. This approach is very similar to how you can automate deployment of portlet to Apache Pluto. You can download sample AjaxPortlet from here

I follow these steps whenever i create a new project

  • I create a simple portlet.xml that does not have any id portlet application id like this

    <?xml version="1.0" encoding="UTF-8"?>
    <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
    version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
    http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">
    <portlet>
    <portlet-name>AjaxPortlet</portlet-name>
    <display-name>Ajax Portlet</display-name>
    <portlet-class>com.webspherenotes.portlet.AjaxPortlet</portlet-class>
    <expiration-cache>0</expiration-cache>
    <supports>
    <mime-type>text/html</mime-type>
    <portlet-mode>view</portlet-mode>
    </supports>
    <portlet-info>
    <title>Ajax Portlet</title>
    <short-title>Ajax Portlet</short-title>
    <keywords>Ajax Portlet</keywords>
    </portlet-info>
    </portlet>
    </portlet-app>

    The value of portlet-name is important for deployment

  • Then i create a pom.xml file which is build script for for my portlet and has custom integration-test target that i use for deploying portlet

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">

    <!-- Change this to something akin to your java package structure -->
    <groupId>com.webspherenotes.performance</groupId>
    <modelVersion>4.0.0</modelVersion>
    <!-- Version of this app -->
    <version>1.0</version>
    <!-- Base name of the war file without .war ext -->
    <artifactId>AjaxPortlet</artifactId>
    <packaging>war</packaging>
    <name>${pom.artifactId}</name>
    <!-- Dependency Version Properties ======================================= -->
    <properties>
    <portlet-api.version>2.0</portlet-api.version>
    <servlet-api.version>2.4</servlet-api.version>
    <jsp-api.version>2.0</jsp-api.version>
    <wps.home>/software/IBM/WebSphere</wps.home>
    <wps.url>http://localhost:10040/wpcert/config</wps.url>
    <wps.admin.name>wasadmin</wps.admin.name>
    <wps.admin.password>wasadmin</wps.admin.password>
    <xmlaccess.path>/software/work/blog/performance/ajax/AjaxPortlet /UpdatePortlet.xml</xmlaccess.path>

    </properties>
    <dependencies>
    <dependency>
    <groupId>javax.portlet</groupId>
    <artifactId>portlet-api</artifactId>
    <version>${portlet-api.version}</version>
    <scope>provided</scope><!-- Prevents addition to war file -->
    </dependency>
    <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>${servlet-api.version}</version>
    <scope>provided</scope>
    </dependency>
    </dependencies>

    <build>
    <finalName>${pom.name}</finalName>
    <plugins>

    <plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
    <execution>
    <phase>integration-test</phase>
    <configuration>
    <tasks>
    <property environment="env"/>
    <exec executable="/bin/bash" dir="${wps.home}/PortalServer/bin">
    <arg line="xmlaccess.sh -user ${wps.admin.name} -password $
    {wps.admin.password} -url ${wps.url} -in ${xmlaccess.path}"/>
    </exec>
    </tasks>
    </configuration>
    <goals>
    <goal>run</goal>
    </goals>
    </execution>
    </executions>
    </plugin>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
    <source>1.5</source>
    <target>1.5</target>
    </configuration>
    </plugin>
    </plugins>
    </build>
    </project>



    In this file you will have to set properties for following things

    • wps.home: Location of portal installation base on your machine

    • wps.url: Config URL for xmlaccess for your portal server it will be http://localhost:10040/wps/config by default

    • wps.admin.name: User name for WPS admin

    • wps.admin.password: Password for WPS admin

    • xmlaccess.path: Path of UpdatePortlet.xml, which is a xmlaccess file that i use for deploying my portlets


    In most of the cases when i create a new portlet only value that will change is xmlaccess.path to point to new updateportlet.xml which is already always in the same directory as that of pom.xml, i bet i can read that directory name using Apache Maven variable but i will have to get some time to find that out

    In my script i have a integration-test target which makes use of ant to execute xmlaccess script that updates the portlet, this ant script gets executed when i execute mvn integration-test

  • The final step is to create a UpdatePortlet.xml file like this

    <?xml version="1.0" encoding="UTF-8"?>
    <request
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="PortalConfig_1.4.xsd"
    type="update"
    create-oids="true">

    <!-- sample for updating a portlet from a new version of the WAR file -->
    <portal action="locate">

    <web-app action="update" active="true" uid="AjaxPortlet.war.webmod">
    <url>file:////software/work/blog/performance/ajax/AjaxPortlet/target/AjaxPortlet.war</url>
    <portlet-app action="update" active="true" uid="AjaxPortlet.war">
    <portlet action="update" active="true" objectid="thePortlet" name="AjaxPortlet">
    </portlet>
    </portlet-app>
    </web-app>

    </portal>
    </request>


    The UpdatePortlet.xml file needs information such as location of .war file, PortletName that i can get portlet.xml, .war file name that i can get from pom.xml and once i change the updateportlet.xml to use correct values i am all set



Once my initial setup is in place i execute the mvn integration-test command to install the portlet for first time or update it, when i do that it take some time to build and then deploy it looks like this

On the fly JavaScript minification using Dojo ShrinkSafe

The Dojo ShrinkSafe is a tool that you can use to minify JavaScript, it can reduce size of JavaScript by close to 1/3 rd or more. You can call ShrinkSafe through commandline, or through Ant as part of your web applications build process. I wanted to see if i can call ShrinkSafe Java API to minify JavaScript.

I built ShrinkSafeFilter which will be part of my .war file and then i applied it to JavaScript URLs and what the ShrinkSafeFilter will do is it will collect the JavaScript file response into String minify it using ShrinkSafe API and return the minifed version to the browser, you can download the sample code from here

My Web application has index.html that includes three JavaScript files which are inside the /WebContent/js folder, this is the screen shot of how the test.js file looks like in the firebug




These are the steps that i had to follow to create ShrinkSafe Filter

  • First i had to create a ShrinkSafeFilter like this


    package com.webspherenotes.performance.minfy;

    import java.io.IOException;

    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.dojotoolkit.shrinksafe.Compressor;

    public class ShrinkSafeFilter implements Filter{


    public void destroy() {
    System.out.println("Entering ShrinkSafeFilter.destroy()");
    System.out.println("Exiting ShrinkSafeFilter.destroy()");
    }

    public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain filterChain) throws IOException, ServletException {
    try {
    System.out.println("Entering ShrinkSafeFilter.doFilter()");

    System.out.println("Received request for " + ((HttpServletRequest)request).getPathInfo());
    SSHttpServletResponseWrapper responseWrapper = new SSHttpServletResponseWrapper((HttpServletResponse)response);
    filterChain.doFilter(request, responseWrapper);
    responseWrapper.finishResponse(response.getWriter());
    System.out.println("Exiting ShrinkSafeFilter.doFilter()");
    } catch (Throwable e) {
    e.printStackTrace(System.out);
    }
    }

    public void init(FilterConfig arg0) throws ServletException {
    System.out.println("Entering ShrinkSafeFilter.init()");
    System.out.println("Exiting ShrinkSafeFilter.init()");
    }

    }

    In the doFilter() method of ShrinkSafeFilter i am wrapping the HttpServletResponse object into the SSHttpServletResponseWrapper method, and then forwarding control to application server for letting it written the static JavaScript file

  • This is how my SSHttpServletResponseWrapper.java looks like
    package com.webspherenotes.performance.minfy;

    import java.io.IOException;
    import java.io.PrintWriter;

    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;

    import org.dojotoolkit.shrinksafe.Compressor;

    public class SSHttpServletResponseWrapper extends HttpServletResponseWrapper{

    StringOutputStream stringOutputStream;

    public SSHttpServletResponseWrapper(HttpServletResponse response) {
    super(response);
    }


    public ServletOutputStream getOutputStream() throws IOException {
    stringOutputStream = new StringOutputStream();
    return stringOutputStream;
    }

    public void finishResponse(PrintWriter writer){
    String inputJavaScript = stringOutputStream.getString();
    long beginTime = System.currentTimeMillis();
    String outputJavaScript = Compressor.compressScript(inputJavaScript, 0, 1, "all");
    System.out.println("Time took to compress " +( System.currentTimeMillis() -beginTime));
    writer.println(outputJavaScript);

    }

    }

    In the getOutputStream() method i am returning a custom ServletOutputStream object that will be used for collecting the actual response into String. Then inside the finishResponse() method i am taking the actual JavaScript output returned by application server into String and calling the Compressor.compressScript(inputJavaScript, 0, 1, "all") method of ShrinkSafe to minify it.

  • THis is how my StringOutputStream class looks like

    package com.webspherenotes.performance.minfy;

    import java.io.ByteArrayOutputStream;
    import java.io.IOException;

    import javax.servlet.ServletOutputStream;

    class StringOutputStream extends ServletOutputStream {

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    public void write(byte[] b, int offset, int length) throws IOException {
    byteArrayOutputStream.write(b, offset, length);
    }

    public void write(byte[] b) throws IOException {
    byteArrayOutputStream.write(b);
    }

    public void write(int b) throws IOException {
    byteArrayOutputStream.write(b);
    }

    public String getString() {

    return new String(byteArrayOutputStream.toByteArray());
    }

    public void close() throws IOException {
    byteArrayOutputStream.close();
    }

    public void flush() throws IOException {
    byteArrayOutputStream.flush();
    }

    }

    This is simple ServletOutputStream class that collects the response in string



This is how the firebug output looks like after i applied the ShrinkSafeFilter to it, did you notice the shinksafe has removed comments from the test.js and also the indentation.

Dojo ShrinkSafe

Dojo Shrinksafe is JavaScript compression system that can reduce size of your JavaScript by close to 1/3rd and it can also be used for combining multiple JavaScript files into one.

If you don't work with a lot of JavaScript, odds are you don't need ShrinkSafe. If, on the other hand, you're pushing browsers or building an amazing "Web 2.0" user experience, ShrinkSafe can make your pages respond faster by reducing the number of HTTP requests needed and by decreasing the size of the files served.

You can use ShrinkSafe in two ways either you can upload the files that you want to ship to its site and it will combine/shrink for you or you can download the latest ShrinkSafe jar file and use it on your local like this


  • If you want to compress test.js into test.min.js

    java -jar shrinksafe.jar test.js > test.min.js


  • If you want to combine and compress test.js, test1.js and test2.js into test.min.js you can do it like this

    java -jar shrinksafe.jar test.js test1.js test2.js > test.min.js