Developing Custom Maven Plugins

Writing Custom Maven Plugins

In this article I would like to point you to a very handy concept i.e. writing custom maven plugins to facilitate in your build process.

If you are a Java developer then you must have been familiar with Maven. Basically maven is a build tool (but its developers say that it is more than that :)). It is a plugin execution engine that helps you write plugins, which can be executed in any maven life cycles.

Basically you will need to be aware of packaging modes, life cycles, build phases and goals of maven. If you are not aware of what all these are, you can find lots of online tutorials that give you good clarity.

Maven community has developed lots of plugins and for most of the use cases you may not need to write your own custom plugin. Sometimes your project build may have specific requiremts that does not get fulfilled by available plugins. In such case, if you have to write one – as I had to write – this tutorial helps you to get your hands dirty with some Java code to write plugins.

Just like POJO in java we have something known as MOJO – Maven plain Old Java Object.

What is a MOJO? (From apache documentation)

What is a Mojo? A mojo is a Maven plain Old Java Object. Each mojo is an executable goal in Maven, and a plugin is a distribution of one or more related mojos.

In short, a mojo is a maven goal, to extend functionality not already found in maven.

So, if you have to write a plugin you are supposed to write one or more mojos.

Here is a sample Mojo(Create a separate maven project):

package com.helicaltech;

/**
 * @author Rajasekhar
 * 
 * Developed at Helical IT Solutions
 */
@Mojo(name = "repack",
        defaultPhase = LifecyclePhase.PACKAGE,
        requiresOnline = false, requiresProject = true,
        threadSafe = false)
public class SampleMojo extends AbstractMojo {
    //The parameter basedir is configured in the plugin configuration
    @Parameter(property = "basedir", required = true)
    protected File basedir;

    //Required = true means it is mandatory to configure the xml
    @Parameter(property = "warName", required = true)
    protected String warName;

    public void execute() throws MojoExecutionException {

        //Write your code here that will get executed
    }
}

Here, name attribut of Mojo is the name of the goal that you would like to run.

The @Mojo annotation defines that the name of the goal is “repack” and that it is not thread safe. It also defines the default phase is the package phase. The last thing is that any member variable can become a parameter. This becomes a parameter for the plugin of a goal.

Example usage of the plugin in POM:

                <plugin>
                <groupId>com.helicaltech</groupId>
                <artifactId>helical-maven-plugin</artifactId>
                <version>${helical.maven.plugin.version}</version>

                <configuration>
                <!--Parameter for the plugin go here -->
                    <basedir>${project.basedir}</basedir>
                    <warName>${project.build.finalName}</warName>
                </configuration>

                <dependencies>
                    <!--You can include the dependencies of your plugins here -->
                    <dependency>
                        <groupId>org.zeroturnaround</groupId>
                        <artifactId>zt-zip</artifactId>
                        <version>1.9</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                    <!--During the package phase the goal repack will be executed -->
                        <phase>package</phase>
                        <goals>
                            <goal>repack</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

The groupId and the artifactId and the version numbers come from the POM file of your plugin.

Once you install the plugin to your maven local repository or your company’s shared central repository so that other developers can use your plugin.

Hope this article helped you and wish you happy coding!

–Rajasekhar
Helical IT Solutions

JAX-RS and Jersey api

JAX-RS and jersey

JSR 311 defines REST support in java. JAX-RS uses annotations to define the REST in java classes.

What is Jersey?

  • Jersey  provieds api/library for JSR 311. We can use it in implementing Restful webservices in a Java servlet container.
  • In server side it helps in scanning predefined classes and identifies RESTful resources. In web.xml we need to register the servlet for web application.
  • It also provies a client library to communicate with a RESTful webservice.

 

How does it works?
Let say the application has the following URL as the request from the client/browser.
http://localhost:8080/web-application/rest/rest_request_path

The servlet maps the required class and method to give correct response to the above request.
The annotations in the classes helps the servlet to pick the right mapping.

Using the internal library Java Architecture for XML Binding (JAXB) we can have the
JAX-RS supports the creation of XML and JSON.
Annotation Description 

Annotation  Description Package Detail
@GET helps in handle the GET request (javax.ws.rs.GET)
@POST helps in handling the POST request ( javax.ws.rs.POST)
@Produces it handles the output type that will be generated ( javax.ws.rs.Produces)
@Path it handles the request mapping for specific url ( javax.ws.rs.Path)
@PathParam helps to  inject values from the URL into a method parameter. (javax.ws.rs.PathParam)
@QueryParam if the request have any query parameters then we can use this to handle using this annotation (javax.ws.rs.QueryParam)
@Consumes it specifies MIME media types a REST resource can consume. (javax.ws.rs.Consumes)
@FormParam the REST resources generally consume XML/JSON. Using this we can read form parameters sent in POST requests. (javax.ws.rs.FormParam)
@PUT handles the PUT method (javax.ws.rs.PUT)
@DELETE handles the DELETE method (javax.ws.rs.DELETE)

 

Maven jersey dependency.
A quick google search will give you maven dependency. Depending upon the project requirement you can find one.

Maven dependency for jersey-servlet

<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
</dependency>

Maven dependency for client
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.22.1</version>
</dependency>

 

Code snippets

/Maps the path for BaseURL/rest/myMapping
package com.helical.restExample

@Path("/myMapping")
public class SampleService {
   @GET
   @Produces(MediaType.TEXT_PLAIN)
   public String plainMessage() {
    return "REST WORLD";
   }

   @GET
   @Produces(MediaType.TEXT_XML)
   public String xmlMessage() {
     return "<?xml version=\"1.0\"?>" + "<message>REST WORLD" + "</message>";
   }


   @GET
   @Produces(MediaType.APPLICATION_JSON)
    public String jsonMessage() {
    return "{\"mesaage\" : \"rest world\"}";
  }


   @GET
   @Produces(MediaType.TEXT_HTML)
   public String htmlMessage() {
    return "<html> " + "<title>" + "REST WORLD" + "</title>"
     + "<body><h1>" + "Welcome to the Rest world" + "</body></h1>" + "</html> ";
   }

}

 

 

Registering the api

In the web.xml we need to configure the jersey servlet to help the mapping

<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.helical.restExample</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>

 

This is good to go. We can run the webservice application to get the desired result.

Sources internet

 

Batch-Updation in Hibernate

Batch Updation in Hibernate

JDBC has long been offering support for DML statement batching. By default, all statements are sent one after the other, each one in a separate network round-trip. Batching allows us to send multiple statements in one-shot, saving unnecessary socket stream flushing.

Hibernate hides the database statements behind a transactional write-behind abstraction layer. An intermediate layer allows us to hide the JDBC batching semantics from the persistence layer logic. This way, we can change the JDBC batching strategy without altering the data access code.

Update code snippet look like this ,

Session session = sessionFactory.openSession();
Transaction txInstance = session.beginTransaction();
ScrollableResults studentInstance = session.createQuery("FROM STUDENT").scroll();
int count =0;
while( studentInstance.next())
{
   Student student =(Student) studentInstance.get(Student.class,StudentID); 
   student.setregNo( regNO );
   session.update(student);
  // 50 - size of batch which you set earlier.
  // For Detail "http://helicaltech.com/batch-insertion-in-hibernate/"
   if(++count %50==0)
   {
      session.flush();
      session.clear();
   }
}
txInstance.commit();
session.close();

----------------------------------

 

PUSHPRAJ KUMAR (BI Developer)

Batch-Insertion in Hibernate


Batch-Insertion in Hibernate

To enable batch-processing  to upload a large number of records into your database using Hibernate.

If you are undertaking batch processing you will need to enable the use of JDBC batching. This is absolutely essential if you want to achieve optimal performance. Set the JDBC batch size to a reasonable number (10-50, for example):

hibernate.jdbc.batch_size 20

the code snippet look like this ,

Session session = sessionFactory.openSession();
Transaction txInstance = session.beginTransaction();
   
for ( int i=0; i<100000; i++ ) {
    Student student = new Student(.....);
    session.save(student);
    if ( i % 40 == 0 ) { 
        session.flush();
        session.clear();
    }
}
   
txInstance.commit();
session.close();

When making new objects persistent flush() and then clear() the session regularly in order to control the size of the first-level cache because by default, Hibernate will cache all the persisted objects in the session-level cache and ultimately your application would fall over with an OutOfMemoryException.

A JDBC batch can target one table only, so every new DML statement targeting a different table ends up the current batch and initiates a new one. Mixing different table statements is therefore undesirable when using SQL batch processing.

PUSHPRAJ KUMAR (BI Developer)

 

JAVA POLICY FILE..

  

JAVA POLICY FILE                                   Apps-File-Java-icon

 

 

The Java™ 2 Platform, Enterprise Edition (J2EE) Version 1.3 and later specifications have a well-defined programming model of responsibilities between the container providers and the application code.

 
The java.policy file is a global default policy file that is shared by all of the Java programs that run in the Java virtual machine (JVM) on the node. A change to the java.policy file is local for the node.

 
The java.policy file is not a configuration file that is managed by the repository and the file replication service. Changes to this file are local and do not get replicated to the other machine.
By using this feature we can control the execution ,
To set the run-time permissions such that Java won’t grant the global permissions. Then you can specify only the permissions you want granted for your app. The key is to run your app with the options below.

java -Djava.security.manager -Djava.security.policy==policyFile.txt MyClass

Note the double equals -Djava.security.policy==policyFile.txt. The double equals == means to use only the permissions in the named file as opposed to the single equal sign -Djava.security.policy=policyFile.txt which means use these permissions in addition to the inherited global permissions.

 
Then create a policy file excluding the permissions you want to deny:

//policyFile.txt
grant codeBase “file:/C:/abc.jar” {
//list of permissions minus the ones you want to deny
//for example , the following give the application
//ONLY AudioPermission and AWTPermission. Other permission such as
//java.io.FilePermission would be denied.
permission javax.sound.sampled.AudioPermission;
permission java.awt.AWTPermission;
}

NOTE :  {app_server_root}/java/jre/lib/security/java.policy. Default permissions are granted to all classes. The policy of this file applies to all the processes launched by `Application Server.

 

 

Pushpraj Kumar

Getters and Setters of JavaScript for a Java Programmer

Getters and Setters of JavaScript for a Java Programmer

In this blog article I will discuss about an important feature of JavaScript – property Getters and Setters. Getters and Setters help you to achieve data encapsulation. The write up is not going to be a comprehensive tutorial but, will provide some insights to understand the world’s most popular programming language properly (from the stand point of a Java Developer – like myself 🙂 ).

Getters and Setters

JavaScript getters and setters work different than Java getter and setters though the purpose is the same – encapsulation. First I will brief about the Java getters and setters and then next I will discuss about JavaScript getters and setters.

A typical Java POJO looks like this.

 

    class Person {
        private String firstName;
        private String lastName;

        Person(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            this.lastName = lastName;
        }

        //The rest of the methods like equals(), toString() and hashCode() may go here.
    }

    

Here getters and setters are typical(mostly generated by using IDEs 🙂 )


        Person person = new Person("John", "Skeet");
        person.getLastName();//Skeet
        person.setLastName("Doe");//Access the method to set the lastName property
    

These methods get and set the member variables firstName and lastName.
The methods g[s]etXXX can be used to have control over the values of firstName and lastName. For more information on this pattern refer to

Why Getters and Setters?

Being a Java developer one may tend to write the same in JavaScript like the following.


        function Person(firstName, lastName) {
            this.firstName = firstName;
            this.lastName = lastName;

            //Function expression; all the vars are hoisted, but assignments are not hoisted.
            //Functions are defined as values. If the value of a var is a function then 
            //it is known as a method.

            //And in JS, private methods don't have access to the public 
            //variables(firstName and lastName)
            //Because inner functions don't share the context of the parent scope

            //Here all the vars(whether value or function) are scoped to the function.
            //They are undefined outside.

            var getFirstName = function() {
                return this.firstName;
            }

            var setFirstName = function(firstName) {
                this.firstName = firstName;
            }

            var getLastName = function() {
                return this.lastName;
            }

            var setLastName = function(lastName) {
                this.lastName = lastName;
            }
        }

        var person = new Person("John", "Skeet");

        //The following is a public method that is available to all the live objects and 
        //future objects of type Person. This method is inherited from an object called the
        //prototype of the Person constructor function

        Person.prototype.toString = function() {
            return this.getFirstName() + " " + this.getLastName();
        }

        document.writeln(person);

    

Or like this…


        function Person(firstName, lastName) {
            this.firstName = firstName;
            this.lastName = lastName;

            //All these are now privileged methods - as what they call -
            //These methods have access to all the vars(values and functions)
            //that are visible with in the function scope along with the properties
            //assigned to 'this' (values and functions) as they are defined on 'this'.

            this.getFirstName = function() {
                return this.firstName;
            }

            this.setFirstName = function(firstName) {
                this.firstName = firstName;
            }

            this.getLastName = function() {
                return this.lastName;
            }

            this.setLastName = function(lastName) {
                this.lastName = lastName;
            }
        }

        var person = new Person("John", "Skeet");

        Person.prototype.toString = function() {
            return this.getFirstName() + " " + this.getLastName();
        }

        document.writeln(person);
    

But, both these patterns are not the ways to write getters and setters in JavaScript. In fact, the first template will throw error.


    Uncaught TypeError: this.getFirstName is not a function(…)
    

Because getFirstName is a variable inside the Person constructor, which is a function that is not visible outside the scope. Because its scope is function scope.

The second template works fine without any errors and it gives the value ‘John Skeet’. But the methods are normal methods (like any other method) of the person object. And by the way, one can directly access the properties without the need of those methods.


        person.firstName = "Osama";//boom
    

So, the correct way of achieving the encapsulation in JavaScript is by using the Object.defineProperty() method.


        var Person = function() {
            var first_name,
                last_name,
                that;

            that = this; //Parent context for use by inner functions

            //Your private functions and other variables go here

            Object.defineProperty(this, "firstName", {
                get: function() {
                    //Here we are not returning firstName. We are returning first_name
                    return first_name;
                },
                set: function(value) {
                    if (typeof value === 'string' && value.length > 3) {
                        first_name = value;
                    }
                },
                configurable: true,
                enumerable: true
            });

            Object.defineProperty(this, "lastName", {
                get: function() {
                    //Here we are not returning lastName. We are returning last_name
                    return last_name;
                },
                set: function(value) {
                    if (typeof value === 'string' && value.length > 3) {
                        last_name = value;
                    }
                },
                configurable: true,
                enumerable: true
            });
        };

        var person = new Person();
        //See, No arguments. First time if you call person.firstName you get undefined
        person.firstName = "John";
        person.lastName = "Skeet";
        document.write(person.lastName); //Skeet
        document.write(person.firstName); //John
        person.lastName = "Doe"; 
        //Now setter is called, but it has rejected the value as Doe is only three characters
        document.write(person.lastName); //Skeet

    

Using the object literal way…….


        var person = {
            name: 'John Skeet',
            get getName() {
                return this.name;
            },
            set setName(name) {
                if (typeof name !== 'string' || name.length < 3) {
                    throw new Error("Person name can't be empty and 
                          should be more than 3 characters");
                }
                this.name = name;
            }
        }

        document.writeln(person.getName());//Expecting John Skeet?
        //Noo... You will get 
        //Uncaught TypeError: person.getName is not a function(…)
        //Because getName is a property of the object person, which invokes a function

        document.writeln(person.getName);//Expecting John Skeet? You got it. Its not a method
        //Now, don't do this...  person.setName("John Doe");
        //Do this

        person.setName = "John Doe";

        document.writeln(person.getName); //John Doe
    

Another alternative by using Java way of getName and setName is ….


        var Person = function(name) {
            var name,
                isValidName = function(name) {
                    if (typeof name !== 'string' || name.length < 3) {
                        throw new Error("Person name can't be empty 
                              and should be more than 3 characters");
                    }
                    return true;
                };

            if (isValidName(name)) {
                name = name;
            }

            this.getName = function() {
                return name;
            };

            this.setName = function(value) {
                if (isValidName(value)) {
                    name = value;
                }
            };
        };

        var john = new Person("Doe");

        document.writeln(john.getName());//Doe

        john.setName("");
        //Uncaught Error: Person name can't be empty and should be more than 3 characters(…)
    

Hope you have enjoyed learning the worlds’s most misunderstood but highly expressive language – JavaScript.
Wish you happy functional programming…

–Rajasekhar
Developer,
Helical IT Solutions.

Expression Language of Spring (SpEL)

Spring Expression Lanaguage (SpEL)

 

There are many expression languages available such as JSP EL, OGNL, MVEL and JBoss EL. SpEL provides some additional features such as method invocation and string templating functionality.

 

The Spring Expression Language (SpEL) supports querying and manipulating an object graph at runtime. This expression language is not directly tied to Spring and can be used independently.

 

The following functionality is supported

Literal expressions , Boolean and relational operators , Regular expressions , Class expressions , Accessing properties, arrays, lists, maps , Method invocation ,Relational operators , Assignment , Calling constructors , Ternary operator , Variables , User defined functions , Collection projection , Collection selection ,
 Templated expressions.

 

In Spring Expression Language, we can reference a bean and its nested properties using a ‘dot (.)’

for example #{ T(java.lang.Math).random() * 100.0 } 

Using toUpperCase() method with String

ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Welcome'.toUpperCase()");
String message = (String) exp.getValue();
System.out.println(message);
o/p WELCOME

 

Evaluating a boolean operation

Expression exp = parser.parseExpression("5==3 and 'text'=='test' ");
boolean result = exp.getValue( Boolean.class);
System.out.println(result);
o/p false

 

We can use many operators in SpEL such as arithmetic, relational, logical etc.
Spring EL supports most of the standard mathematical, logical or relational operators.

Relational operators – equal (==, eq), 
not equal (!=, ne), 
less than (<, lt),
 less than or equal (<= , le), 
greater than (>, gt), 
and greater than or equal (>=, ge).
Logical operators:– and, or, and not (!).
Mathematical operators:- 
addition (+),
Subtraction (-),
Multiplication (*), 
division (/),
modulus (%) and
 exponential power (^).

 

In SpEL, we can store a value in the variable and use the variable in the method and call the method. To work on variable, we need to use StandardEvaluationContext class.

 

Example of Using variable in SPEL

public class Rectangle {
private int length;
private int width;
public int getLength() {
return length;
}
public int getWidth() {
return width;
}
public void setLength(int length) { this.length = length; } 
public void setWidth(int width) { this.width = width; } public int area(){ return length*width; } }

The above class is a bean which is used in the Expression Language in the below class

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

public class Test {
public static void main(String[] args) {
Rectangle rectangle= new Rectangle();
StandardEvaluationContext context=new StandardEvaluationContext(rectangle);

ExpressionParser parser = new SpelExpressionParser();
parser.parseExpression("length").setValue(context,"5");
parser.parseExpression("width").setValue(context,"15");

System.out.println(rectangle.area());
}
}

Spring expression language efficiently sets the length and width property of the bean to 5 and 15 then the area method is invoked in the bean it gives the appropriate result.

Sources: internet

Validation Framework in HDI

Validation Framework in HDI

Q) What is validation framework?
Ans) This framework helps to validate the form data in the server side.

 

Q) Which data is validated?
Ans) Every request to the server (GET or POST method) have some parameters which is generally known as formData. The formData is generally a JSON(JavaScript Object Notation) Object. If the formData is not a JSON Object then it is either a key value pair, which we generally refer as query parameters.

Example of request.

 

GET Method

http://www.helicaltech.com/addUser.html?name=Arnold&age=28&mobile=98883888&dateOfRegistration=12/08/2013&action=addUser&qualification=matricualtion 

 

POST Method

http://www.helicaltech.com/adduser.html
           name=Arnold
           age=28
           mobile=98883888
           dateOfRegistration=12/08/2013
           qualification=matricualtion
           action=add

 

POST Method using formData as JSON object

http://www.helicaltech.com/adduser.html

formData{
   "name":"Arnold",
   "Age":28,
   "mobile":"98883888",
   "dateOfRegistration":"12/08/2013",
   "action":"add",
   "qualification":"matricualtion"}

 

Q) How to configure the validation?
 Ans) Basically two files are to be considered for configuring the validation

  1. regex.properties
  2. validation.xml

 

Q) What is regex.properties?
Ans) regex.properties file is a property file. Any data validation regex can be configured here. See more about regular expression here
Example of regex.properties

email=^[A-Za-z0-9._%'-][email protected][A-Za-z0-9.-]+\\.[a-zA-Z0-9]+$
IPAddress=^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
text=^[a-zA-Z0-9\\s\\._%\\{\\}\\(\\)%\\?"':@,/]*$
fileName=^[a-zA-Z0-9][a-zA-Z0-9 \\-\\.\\_\\~\\&\\(\\)\\[\\]\\:]+$

here email is the regex key ^[A-Za-z0-9._%’-][email protected][A-Za-z0-9.-]+\\.[a-zA-Z0-9]+$ is regex value.

 

Q) What is validation.xml?
Ans) This file we have to map the url which we are going to validate. The url mapping has to be configured in the <mappings> tag

<mappings>
   <url pattern="/addUser.html" definition-file="createUsers.xml" />
</mappings>

 

This means the “/addUser.html” is the url whose request parameters needs to be validated. The definition-file attribute holds the xml file-name where the actual rules are configured.

 

Q) How rules are configured?
Ans)The rules are pretty simple. They are configured in the xml file with the request paramters key as the element and rules as the attribute.

 

For example the createUser.xml is configured as following

<?xml version="1.0" encoding="UTF-8"?>
<formData>
   <action type="text" required="true"/>
   <name type="userName" />
   <age type="number" requiredIf="action" condition="=" value="add" minLength="6" maxLength="60"/>
    <qualification type="text"/>
    <dateOfRegistration type="date" maxLength="60" requiredIf="qualification" condition="=" value="engineer" />
</formData>

 

Q) What is type attribute?
Ans) The type attribute holds the key defined in regex.properties. This attribute is not mandatory. If the request parameter is not empty then this regex is validated against the value of the request parameter.

The type attribute can have multiple key name separated by ,
eg type=”text,notNumber,notSpecialCharaters” here each key regex is validated and, if any of the key is found to be invalid the data is considered to be invalid.

 

Q) What is required attribute?
Ans) The required attribute is used when the request parameter should not be empty. In the above example the action and the name is required.
Q) What is minLength attribute?
Ans) The minLength attribute defines the minimum length (minimum characters) of the value for the request parameter.

 

Q) What is maxLength attribute?
Ans) The maxLength attribute defines the maximum length (maximum characters) of the value for the request parameter.

 

Q)What is length attribute?
Ans) When we know that the request parameter has to have the exact length then we can use this attribute.

 

Q) What is requiredIf attribute?
Ans) Sometime one parameter is dependent on another parameter . For example the dateOfRegistration is required if qualification is engineer.

With requiredIf attribute two more attribute condition and value need to be set

The condition attribute can have any operator eg. =, <= , >=, ==, != etc

The value attribute should have the value which is a rule.

<qualification type="text"/>
    <dateOfRegistration type="date" maxLength="60" requiredIf="qualification" condition="=" value="engineer" />

Login to a website and take screenshot using PhantomJS on the server side

Login to a website and take screenshot using PhantomJS on the server side

In this blog I will discuss about taking screenshots using PhantomJS by logging in to a site and taking screenshot a particular link or URL. I am not going describe how PhantomJS can be invoked on the server side.

Taking screenshots of visualizations with SVGs is not an easy task at least in Java. I have tried to produce the pdf of web pages with SVG content using the Apache Batik library but was not very successful. So, I have tried the alternatives and one of the options was PhantomJs.

PhantomJS is a headless browser and is capable of taking screenshots of complex visualizations otherwise difficult to capture. So, phantom is as good as Mozilla or Chrome but runs in-memory, so it is headless. PhantomJS has many applications and one of them is that it can be used to produce quality reports in different file formats like pdf and images.

Using ProcessBuilder API in Java we can invoke PhantomJS by providing the path of the Phantom executable, a javascript file that the PhantomJS uses to render the web page, and the location of the file where you want to save the generated file by PhantomJS. Once the pdf is generated it can be used for any purpose like mailing it or scheduling it or serving the user with a downloadable file.

The following is the screenshot.js file from PhantomJS web site. I have modified the code to log in using PhantomJS and take the screenshot and save it as a file on the file system.

 

//Here the command-line arguments that you've passed when invoking the PhantomJS executable 
//are obtained as an array. In this case I have passed phantom-js.exe as first argument, 
//the screenshot.js as the second argument.

//Note that The third argument is accessed as args[1] in the javascript file and the numbering continues.
var system = require('system');

// Web Address (URL) of the page to capture
var url = system.args[1];

// File name of the captured image
var file = system.args[2];

var reportPage = require('webpage').create();

// Browser size - height and width in pixels
// Change the viewport to 480x320 to emulate the iPhone
reportPage.viewportSize = {
    width: 1920,
    height: 1080
};

reportPage.paperSize = {
    format: 'A4',
    orientation: 'portrait',
    footer: {
        height: "1.0cm",
        contents: phantom.callback(function (pageNum, numPages) {
            return "<div style='font-size:13px;font-weight:normal;'>
                    <span style='text-align:left'>Confidential</span>
                    <span style='margin-left:44em'>" + pageNum + " of " + numPages + "</span></div>";
        })
    }
};

reportPage.settings.localToRemoteUrlAccessEnabled = true;
reportPage.settings.webSecurityEnabled = false;

// Set the User Agent String
// You can change it to iPad or Android for mobile screenshot
reportPage.settings.userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5";

var loginPage = require('webpage').create();

function getLoginUrl() {
    var loginUrl,
        domain = system.args[3],
        username = system.args[4],
        passCode = system.args[5],
        organization = system.args[6];

    //Form the login url. As a GET Request.
    loginUrl = domain + "?j_organization=" + organization + "&j_username=" 
               + username + "&j_password=" + passCode;

    return loginUrl;
}

function saveReport() {
    var logoutPage = require('webpage').create();
    reportPage.open(url, function (status) {
        if (status !== "success") {
            console.log("Fatal Error. Could not open web page : " + url);
            phantom.exit();
        } else {
            window.setTimeout(function () {
                reportPage.render(file);
                console.log("Download the screenshot : " + file);
                //Logout
                logoutPage.open("./j_spring_security_logout");
                phantom.exit();
            }, 3000);
        }
    });
}

//Now if login is successful, take the screenshot
loginPage.open(getLoginUrl(), function (loginStatus) {
    if (loginStatus !== "success") {
        console.log("Fatal Error. Couldn't login to get the report screenshot.");
    } else {
        // Render the screenshot image
        saveReport();
    }
});

 

Also note that when we start a process using command-line/shell script, do not forget the read the InputStream, and the ErrorStream of the java.lang.Process.
Hope you have followed the comments and understood the how to part of it. If you have any questions, please post them so that I will answer the questions.

Wish you happy coding and thanks for reading the article.


–Rajasekhar
Java BI Developer,
Helical IT Solutions.

JMX -Java Monitoring Extension

Java Monitoring Extension

JMX is one of the most useful way in java environment to debug applications.

We can use different JMX tools to connect to the JMX  port and monitor the status of our application.

Information of the memory usage, the total number of instances, the object references etc can be tracked easily.

In tomcat we can use the startup scripts to set all kinds of parameters, or we can also enable JMX access by setting the CATALINA_OPTS environment variable.

On Unix machines we can create a file setenv.sh inside Tomcat’s bin   directory with the following content:

export CATALINA_OPTS="-Dcom.sun.management.jmxremote"

This is read automatically during the startup.

On Windows machine, this can be set via setenv.bat.

We can add username and password to secure this port

export CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=8090 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"

After JMX port is setup we can connect to it using the jconsole tool or jvisualvm tool which is present in the jdk bin installation directory.

We can double click to lauch it or type “jconsole” or “jvisualvm” from the command prompt.

Once it is opened we can connect to it by typing the remote address and port number of the server.

If we have set the credentials at the server side then we need to provide them.

jconsole1

The JConsole interface in JDK is generally composed of the following six tabs:

Summary displays summary information on the JVM and monitored values.
Memory displays information about memory use.
Threads displays information about thread use.
Classes displays information about class loading.
MBeans displays information about MBeans.
VM displays information about the JVM.

jconsole

Jvisualvm tool has many feature as compared to jconsole. We can analyze a heap dump and take memory snapshots, thread dump.

We can also use sampling option to take some sample of the desired classes in the memory.

Using jvisualvm we can also load  heap dump of a any server and then analyze the heap dump offline.

jvisualvm