Friday, August 30, 2013

Aspect Oriented Programming (AOP) using CDI for Java EE

As defined by wikipedia, aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. AOP forms a basis for aspect-oriented software development. (Aspect oriented programming)
Using AOP we break down our program logic into distinct parts called concerns. Aspects enable the modularization of concerns such as transaction management that cut across multiple types and objects. 
Certain terms and terminology commonly used in AOP are:-
  • Aspect: a modularization of a concern that cuts across multiple classes.
  • Join point: a point during the execution of a program
  • Advice: action taken by an aspect at a particular join point.
AOP has been very common in Spring Framework and is also available in Context & Dependency Injection (CDI) for Java EE. 
The benefits of using AOP are:-
  1. modularization of system level coding i.e. logging, transaction, security 
  2. minimal coupling and duplication of code making it easier to add new functionalities.
  3. faster development as developers can focus mainly on the business logic rather than thinking of cross-cutting concerns such as security, transaction, logging etc. The business logic looks clear and does not have logging, security, transactional details.

Some example areas where AOP can be used:-

  1. Logging - We can write aspect around methods so that we can log before and after states of a method without actually putting logging statements in the actual method.
  2. Transaction management - in applications where transaction has to be managed manually, we can write aspects to begin and commit or rollback transactions depending on success or failure of the business method.
  3. Security - we can apply method level security around a method. So we do not have to implement security and role check in every business method. Aspect can be written that will be fired before a method is invoked and incase the user is not authenticated it will return an exception.
  4. Checking and using cached data before data access from database - we can write aspects around a data access method which will access the cache to see if the data is present. Incase the data is present it will return the data from the cache. Otherwise it will make data access call to the database and also add the returned data to the existing cache. Sample application below will use this as an example. 

Sample Application

Since we are developing using CDI for Java EE, I will present a sample implementation of AOP and cross-cutting using Java EE. This application uses Glassfish 4 as the application server and using Java EE.
 In this application I will show how we can write an Aspect around a web service method. This aspect will be fired before and after the web service method and can be used for security validation as well as checking cached data before making a DB call.
 We have a RestFulService service, which handles RESTful calls. Method retrieveRecordByResource handles the @Get RESTful call and retrieves all the parameters that are sent as part of the RESTful service. 
We will create an aspect around this call, which will
  • monitor the variables coming as input to the REST call 
  • response returned as part of the REST call
  • will modify variables before the call reaches retrieveRecordByResource method.
Code for Advice:-

In the code above, we create an advice class and method checkCache, with annotation @AroundInvoke. @AroundInvoke defines an interceptor method that interposes on business methods. 
Line 42, calls the proceed api of InvocationContext. Before this call we see that we have extracted the input parameters that came as input from the REST service call. It also returns returnParam which is the output after the call to our business method retrieveRecordByResource. 
Line 31 to 42, we see that we have extracted input parameters before the call to business method and we can manipulate these variables. We can do logging, security check, transaction management etc. before actually calling the business method. 
Line 44, we have control of the output parameters and we can log or manipulate these parameters. 

Line 17, defines an annotation @CacheResource. We need to define an interface CacheResource for the same.


In simple terms this interface and annotation @CacheResource, link our advice and the business class.
The interceptor is defined in WEB-INF/beans.xml:-

This configuration defines our interceptor. 

Conclusion:-
AOP is a very useful and powerful feature of OO programming. CDI brings AOP and dependency injection (DI). We can integrate AOP with caching using caching frameworks like JCache or EhCache.
CDI is the Java standard for dependency injection and interception (AOP). You can read futher about the same in JSR 299.

Wednesday, August 21, 2013

GlassFish 4 plugin with Eclipse Juno

Java EE 7 & GlassFish 4 are getting hot in popularity. With GlassFish 4 being adopted by many enterprises for their application development and EAI, hence I thought of writing this post of a quick way to introduce GlassFish into yours and your eclipse's life.

The GlassFish Server is a compliant implementation of the Java EE 7 platform. 

The GlassFish Eclipse Plugins
The starting place for Eclipse are the GlassFish Eclipse plugins. They moved into the Oracle Enterprise Pack for Eclipse (OEPE) project a while back and are still there to be installed and configured separately.



Install the Plugin
This works as expected. If you stick to the update site you simply go to Preferences->Install/Update->Available Software Sites and make sure that the above mentioned site is defined and checked. Install the GlassFish Tools and the Java EE 6 and/or Java EE 7 documentation and sources according to your needs. Click next two times, read through the license and check accept. Click Finish to install. The download gets everything in place and you have to finish the installation with a re-start.

I had some of the componenet already installed hence in the below pic you will not see all the components that will be available for download.


Add GlassFish as your server

In the server type, look for Glassfish.  If not there, click ‘Download additional server adapters’.  Look for and click on Glassfish Tools and click Next. Go through prompts to download.  Eclipse will likely need to be restarted. Then go through steps to set up a new server again.



You can also access the Glass fish admin console using URL - http://localhost:4848/



Thursday, August 15, 2013

Creating sample Struts 2 Web application and deploying on Tomcat 7

This blog is extension of Configuring Eclipse's Dynamic Web project for Struts 2 with Maven and deploying on Tomcat 7.. In the previous blog you would have learned how to configure an eclipse dynamic web project with maven. Now I will use the same project to configure a sample struts 2 application.


We are going to create a sample application, that will provide a login screen to the user and prompt them to login. Incase of error it will show the error page and do simple validation using struts.


Our Struts application will consist of following components:-

src/main/java/com.struts2.demo.action Actions:
  1. LoginAction extends ActionSupport - this action class will have the logic to validate the user name/pwd and direct the call.
  2. MissingAction extends ActionSupport - empty action class for redirecting empty requests to a missing page.

src/main/resources/ struts files:

  1. struts.xml file
  2. sampleapp.xml - included struts file, to break up the configuration file into multiple files


src/main/resources/com.struts2.demo.action resource files:

  1. LoginAction-validation.xml - struts validation xml file. Does simple required string validations.
  2. package.properties - localization support properties file

src/main/webapp/sampleapp jsp files:

  1. error.jsp
  2. Login.jsp
  3. Missing.jsp
  4. src/main/webapp/index.html

src/main/webapp/WEB-INF: web.xml

1 Action classes -  

LoginAction 

/**
 * 
 */
package com.struts2.demo.action;

import com.opensymphony.xwork2.ActionSupport;

/**
 * @author 
 *
 */
public class LoginAction extends ActionSupport {

public String execute() throws Exception {

        if (isInvalid(getUsername())) return INPUT;

        if (isInvalid(getPassword())) return INPUT;

        return SUCCESS;
    }

    private boolean isInvalid(String value) {
        return (value == null || value.length() == 0);
    }

    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    private String password;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


}

MissingAction


package com.struts2.demo.action;

import com.opensymphony.xwork2.ActionSupport;


public class MissingAction extends ActionSupport {
}


2 Resource Files

LoginAction-validation.xml

<?xml version="1.0"?>
<!DOCTYPE validators PUBLIC
          "-//Apache Struts//XWork Validator 1.0.2//EN"
          "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
  <field name="username">
    <field-validator type="requiredstring">
      <message key="requiredstring"/>
    </field-validator>
  </field>
  
  <field name="password">
    <field-validator type="requiredstring">
      <message key="requiredstring"/>
    </field-validator>
  </field>

</validators>


package.properties

requiredstring=  ${getText(fieldName)} is required.
password= Password
username= User Name
Missing.message=  You have successfully logged in.

Error.message= Login/Pwd is wrong.

struts.xml


<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
  <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
  <constant name="struts.devMode" value="true"/>
  
  <include file="sampleapp.xml"/>
  
</struts>

sampleapp.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
  <package name="sampleapp" namespace="/sampleapp" extends="struts-default">
    <action name="Login_*" method="{1}" class="com.struts2.demo.action.LoginAction">
      <result name="input">/sampleapp/Login.jsp</result>
      <result type="redirectAction">Missing</result>
      <result name="error">/sampleapp/error.jsp</result>
    </action>

    <action name="*" class="com.struts2.demo.action.MissingAction">
      <result>/sampleapp/{1}.jsp</result>
    </action>
      
  </package>
</struts>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="struts_blank" version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>Struts</display-name>

  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>
      org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
    </filter-class>
  </filter>

  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
</web-app>


3. JSP files

error.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>Login error</title></head>

<body>
<p>
    <s:text name="Error.message"/>
</p>

<ul>
    <li><a href="<s:url action="Login_input"/>">Sign On</a></li>
    
</ul>

</body>

</html>

Login.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
    <title>Sign On</title>
</head>

<body>
<s:form action="Login">
    <s:textfield key="username"/>
    <s:password key="password" />
    <s:submit/>
</s:form>
</body>
</html>

Missing.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
    <title>Sign On</title>
</head>

<body>
<s:form action="Login">
    <s:textfield key="username"/>
    <s:password key="password" />
    <s:submit/>
</s:form>
</body>

</html>

index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <META HTTP-EQUIV="Refresh" CONTENT="0;URL=sampleapp/Login_input.action">
</head>

<body>
<p>Loading ...</p>
</body>
</html>


Your project structure in Eclipse should look like this:


Now when you deploy this application on Tomcat, you can access it via url -  http://localhost:8080/strutsapplication/

This will direct you to URL - http://localhost:8080/strutsapplication/sampleapp/Login_input.action and show the login page.

If you enter 1 as the password, it leads to error page.

If you do not enter anything in login or pwd fields, then validation is kicked and error messages are shown.

Configuring Eclipse's Dynamic Web project for Struts 2 with Maven and deploying on Tomcat 7.

This post will introduce you to creating a new Struts 2 dynamic web application to run on Tomcat 7. 

The motivation behind this post was, that I was looking for a archetype to create a web app that could be configured on Eclipse as a Maven project in Facets form and could be run directly on Eclipse using Tomcat 7 configured on eclipse. This might seem very simple to many, but lot of people get confused in setting up project in facets form, which can be bundled using maven in a way that it can be easily deployed on tomcat.

If you intend to create a struts web app that you would want to run on jetty server for development then you can use following archetypes to create sample applications. 


  • struts2-archetype-convention
  • struts2-archetype-blank
Once created you can run these applications using mvn jetty:run command.

Now back to creating a struts 2 based dynamic web application on Eclipse, that will run on Tomcat 7. Before starting with the development, you will need following software configured or downloaded.

  1. Eclipse IDE
  2. Tomcat 7 or 6 configured in Eclipse IDE.
  3. Maven 3 on Eclipse
  4. jdk 6 or 7


We start with creating a new Dynamic Web project in Eclipse

Create a new dynamic web project, New->New Dynamic Web Project in eclipse



Click next and again click next. On Web Module section, click the checkbox for "Generate web.xml dd"



Now click Finish button.

Now the transformation of the dynamic web application to a struts 2 application that could be bundled using maven and run on Tomcat starts.

Right click on the project and scroll to Configure, then click on Convert to Maven Project... link.



Enter the groupid, artifact id and select the packaging as war. Then click Finish button.

Now your project has been converted to a maven project. You could achieve up to this stage by running a struts 2 archetype. But I wanted to explain you this, in case you wanted to setup a web project from scratch.


If you check in your project properties, Project Facets section - you will find at the project is in facets form with Dynamic Web Module 3.0, Java 1.6 & JavaScript 1.0 selected.






 If you would have used an archetype to create the maven project then you would have to convert the project into Facets form from this section. That would have been an additional step.

Now add following dependencies in your pom.xml



<properties>

<struts2.version>2.3.8</struts2.version>

</properties>

<dependencies>

<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts2.version}</version>
</dependency>

<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-config-browser-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>

<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-junit-plugin</artifactId>
<version>${struts2.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
</dependencies>


Now we create required folders, so that everything could be bundled properly.

Right click on Java Resources in your project and create following new Source Folder

  • src/main/java
  • src/main/resources



Delete existing WebContent folder

Scroll to src folder, you will find src/main with java & resources folders. Create new webapp folder.

Now your folder structures in Eclipse should look exactly like this.




Previous step is important, because that is the structure of the project that we want to achieve. So make sure your project structure exactly matches this.

Your Eclipse Deployment Assembly should look like this:-


Now we start configuring the project so that our struts 2 application can run.

Create a WEB-INF folder inside webapp, and create a web.xml file. Content of your web.xml file will be as follows:-

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="struts_blank" version="2.4"

         xmlns="http://java.sun.com/xml/ns/j2ee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>Struts Blank</display-name>

  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>
      org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
    </filter-class>
  </filter>

  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
</web-app>


As you see that I have added struts 2 filter and filter mapping. This is required to run the struts2 application.


Now try running maven build, run mvn build or install from eclipse. You will need internet connection so that maven can download these dependencies from repository.This will package your empty project as war and populate target folder.


If you are getting an error like - Cannot nest 'Project/src/main/java' inside library 'Project/src

Then go to org.eclipse.wst.common.component,xml file in .settings of your project (visible from Navigator view) and make sure the contents of the file look like this. Otherwise update.


<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0"> <wb-module deploy-name="strutsapplication"> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/> <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>/> <property name="context-root" value="strutsapplication" />/> <property name="java-output-path" value="/strutsapplication/target/classes"/> </wb-module> </project-modules>


Now your project is ready for creating a sample web application using struts 2 to run on Tomcat 7. Check my new blog http://javaredhot.blogspot.com/2013/08/creating-sample-struts-2-web-application.html for the same.

Creating sample struts 2 web application