Thursday, 7 November 2013

OGNL Implementation in Struts

Struts 1.x

Struts 1.x used expression language(EL) which uses JSTL as its base.  Struts-EL tag classes are subclasses of Struts tag classes. The EL has basic object graph traversal, but it is not very powerful  and also the  indexed property support is very weak.

Struts 2

Struts 2 was released in 2007 with many exciting features. As compared to Struts 1.x, it simplified the app development task by automating data transfer(form beans to data beans and vice versa as in Struts 1.x) and type conversion(parsing string into double/integer along with exception resolution was to be done in Struts 1.x).

OGNL

With Object Graph Navigation Language(OGNL) in Struts 2, data can be transferred with complex data structures like List and Map. User-defined types can be used with the help of custom converters, which are quite easy to write. OGNL acts as a layer between Struts 2 framework and Java-based processing unit.

ValueStack

OGNL greatly relieves developer from extra coding and maintenance effort. OGNL binds Java-side data directly to the corresponding fields in view layer. Built-in data converters save conversion work while data passes to or from Java environment. Field names in HTML can be generated using OGNL expressions to bind them directly to corresponding Java property and thus eliminates redundant code in Action classes. On contrary to the standard JSP mechanism for binding objects into the page context for access in Struts 1.x, Struts 2 uses ValueStack technology by which  taglibs can access values without coupling view to the object type it is rendering. ValueStack is set as OGNL’s root object. It contains application specific objects like action and also the model objects.

Context Map



OGNL context is set to ActionContext. ActionContext is a container of objects in which action is executed. We get a reference of it by simply calling ActionContext.getContext(). There are other objects in ActionContext like Maps(referred to as context or context map) to represent application, session and request contexts.

Data Access

The root object is referred simply by its name, without any special symbol prefixing it. Since Action instance is always pushed on ValueStack, which is the OGNL root, references to Action properties can omit pound sign. But for rest of the objects in ActionContext, ‘#’ has to be used.
Example: To refer to Action property:


<s:property value=”firstName”/>

For other objects:


<s:property value=”#session.username”/>   Or

<s:property value=”#session[‘username’]/>

Similarly we can refer to properties of request, application or attr (attribute in scope).
Collections can also be referred using OGNL.List is referred by {value1, value2,....}


<s:select label=”Continent” list=”{‘Asia’, ‘Europe’, ‘Africa’} value=”defaultContinent”/>

Alternatively, the list can be populated in Action class with its getter, setter provided.

Map is referred by #{key: value ,....}


<s:select label=”Continent” list=”#{‘first’:‘Asia’, ‘second’:‘Europe’,’third’: ‘Africa’} value=”defaultContinent”/>

In case of Set, we can check whether an item exists in it or not using ‘in’ or ‘not in’.


<s:if test=”’Asia’ in {‘Asia’, ‘Europe’, ‘Africa’}
        Exists in the set
</s:if>

Percent (%) symbol

It is used to force OGNL expression evaluation, which results in querying ValueStack for the property.


<s:property name=”%{continent}”/>  (‘#’ accesses named ValueStack property)

At (@) symbol

It is used to refer static properties and method. We need to enable it in properties file by setting-


struts.ognl.allowStaticMethodAccess=true
and then access like this-

<s:property value="@com.test.TestClass@STATIC_PROP" />

Dollar ($) symbol

Used in JSTL expressions.


‘OGNL’ name might have sounded like something difficult to first time readers. But I’m sure, after reading this post you must be ready to shake hand with OGNL!!


Friday, 6 September 2013

Challenging Work

When do you find a given task to be hard/difficult/challenging? During school days we used to call it as 'hard', in college days as 'difficult' and in job days as 'challenging'!

  1. The work needs to be delivered in less than how much time you estimated for it.
  2. You don't have clarity on the work but delivery date is fixed.
  3. Problem statement is clear but you don't know how to do it.
  4. Multiple tasks are assigned to you and the priority keeps on changing.
  5. You need to take leave for some reason and all of a sudden an easy task becomes challenging.
  6. Sometimes you do not like to work on a particular task and this is why it is challenging for you.
  7. You are stressed and everything looks challenging to you.
  8. When delivery date is very close, work appears as extraordinarily challenging.
  9. Someone couldn't do it and the same work gets delegated to you...especially when that 'someone', you consider to be a techie (Such situation can have positive impact too..you take it up as a challenge!).
  10. You are sincerely working on the task and your boss repeatedly asks you 'Done?'
  11. A combination of the above.

Have I missed any scenario?



Wednesday, 31 July 2013

When to use AngularJS and when to use Backbone!

In this post I am documenting my thoughts on when to use Backbone vs AngularJS with the help of examples (This post is not a comparison between AngularJS and Backbone).

E-Commerce Application

It should not be a single page app (unless we are trying to address few small use-cases or building shopping site for a small merchant). 

We need a framework which provides support for data-binding. Struts OGNL, Spring MVC, JSF EL etc work fine but these are backend technologies. For a modern web-app we need similar support using JavaScript. AngularJS from Google offers this kind of functionality and hence recommended. 

Online HTML/CSS Builder 

Edit functionality becomes more important than view/read. It should be a single page app (User experience is good in this case). 

A lot of UI specific work involved - like drag n' drop, animation effects etc. Text rendering is limited. AngularJS can be used to create a SPA but Backbone is recommended.

Interactive Reporting Tool

Dynamic UI, report editing and cool UI effects. Backbone is recommended. Please not that Backbone alone is not sufficient so we must use a suitable js-tech-stack which is known to work properly with Backbone.

Content Management System

Data representation in TEXT format. Edit functionality using regular forms. 
Single Page App with content getting managed in various Views. AngularJS is recommended.

Question - What will I use if I have to build GMail? 
Answer - AngularJS :)

* In most of the projects where I use Backbone, I define proper architecture for the JS layer, design with the help of a complete js-tech-stack and let backbone play its role (I do not let backbone drive the architecture of front-end).

Friday, 26 July 2013

My Findings with ModelDriven Struts Action

We are well aware of the usual action classes of Struts- values of the fields entered in UI populate the corresponding action properties. In case of ModelDriven action class, the properties of its model class get populated. Here is an example of it:


public class EmployeeRegistrationAction extends ActionSupport implements ModelDriven<EmployeeData>{

 private EmployeeData employeeData = new EmployeeData();

 
 public EmployeeData getModel() {
  return employeeData;
 }

 //Rest of the methods

}


public class EmployeeData implements Serializable{

 private String firstName;
 private String lastName;
 private String city;

 //setters & getters

}


The next step is to implement the getModel() method in such a way that it returns the application domain object, in our example we return the EmployeeData object. We can either use ModelDriven<Object>, where getModel will return Object or can specify the model class as above.
Prerequisite for using such action class is that it should implement ModelDriven interface, for which Model Driven Interceptor should be applied to action. Since this interceptor is part of the default interceptor stack, it is applied to all actions by default. Wow...we don't have to do anything out of the way to use it!

JSP:

<s:form method="POST" action="/registration.html" name="registrationform" enctype="multipart/form-data" id="registrationform">

     <s:textfield name="firstName" placeholder="First Name"/>
     <s:textfield name="lastName" placeholder="Last Name"/>
     <input type="submit" class="button" value="Create Employee"/>

</s:form>


Since I did not want to navigate to any other page and wanted the json response by staying on same page, I used ajaxSubmit(). I'd used ajaxSubmit earlier too and json response was returned just as I expected. Xml entry:

<action name="registration" class="employeeRegistrationAction" method="createEmployeeRecord">

 <result type="json"></result>

</action>


Javascript:

var registrationFormOptions = {

 resetForm : false,// reset the form after successful submit
        success   : showRegistrationResponse

    };


$("#registrationform").validate({

 submitHandler:function(form){
 //perform not-null validations. If fine,submit. else show validation error messages
 $(form).ajaxSubmit(registrationFormOptions);

 }
});

But in case of ModelDriven, json response that I was getting, was surrounded by <pre style="word-wrap: break-word; white-space: pre-wrap;"> tag. I thought of extracting json sitting inside the <pre> tag, in javascript. Thankfully I was saved from it, just one minor addition and it worked:


var registrationFormOptions = {

 resetForm : false,// reset the form after successful submit
 success : showRegistrationResponse,
 dataType: 'json'
};


Addition of dataType: 'json' in the options worked wonders. I was getting a clean json response!


Monday, 8 July 2013

Don't eval(Javascript)

I was looping through the Department data-departmentVO_1 to departmentVO_5 (each contained DepartmentVO complexType's object) and display info against the respective department.


for ( var x = 1; x < 5; x++) {

   var info = "departmentVO_"+x;

   var department = data.info;

   $("#totalEmployeesDepartment_"+x).val(department.departmentVO.totalEmployees);

}

Surprisingly javascript was throwing error for department being undefined. That indicated data.info was not working as I expected.

I searched for concatenating loop variable to access a variable in javascript and found out that something on this line would work:


eval('var department = ' +data.info);

w3schools says: The eval() function evaluates or executes an argument.
If the argument is an expression, eval() evaluates the expression. If the argument is one or more JavaScript statements, eval() executes the statements.

But misuse of eval has led to serious concerns like security issues or performance issue or often simple bugs. Also each invocation of eval() creates a new instance of the JavaScript interpreter and hence creation of new execution context. In short additional resource being put to use. Plus such code is harder to debug and maintain (Reminds me of 'goto' statement...we can still use it, but difficult to find problems). So it is better to check if there is any better, neater and safer alternative.

I decided not to use eval in my case. Understanding what I was trying to obtain, I realized that square brackets can be used instead of literal dot-names. So my code:


var department = data.info;

replaced with

var department = data[info];

I'm convinced, so lets use eval with care!

Thursday, 4 July 2013

Struts + Ajax + JSON

It wasn't my first experiment with Struts or Ajax or jsp! Despite this fact, I ran into problems and had to spend time to fix it. So let me share what dawned to me (I'm specifically avoiding term 'what I learnt'...since I already knew it).

My home.action had jsp with div in it which would open as a popup with a link click.

<s:textfield id="fullName" value="%{datamodel.fullName}" placeholder="Full Name"/>
In brief, on click of the link, it was supposed to show the div with values populated, fetched from db.

Action class with a method to serve my need was already in place to fetch data and populate in bean. However the action was returning another jsp. Using the same method in Action class, making an additional entry which returned result type as json, did the job.

<action name="homePage" class="HomePageAction" method="loadUserData">
     <result type="json"></result>
</action>

I wrote a function to send ajax request (to be called with link click):

function loadData(index){

var userName = $("#userName").val();

$.ajax({

type: "GET",

url : '/site/loadUserData.action?userName ='+userName,

success: function(data){

     showProfile();

   }

 });

}

I was getting 'data' in success part of ajax request. Happy! I was expecting the bean values to be displayed on the pop up since bean is populated and popup opens after that. But I continued to see blank fields. Disheartened!

The reason behind it was straightforward(though it didn't trigger me while I was working on it!): jsp got rendered when home.action was called. That time bean was not having values. Jsp displayed/resolved the values it had at that time. Now when I click link, send ajax request, get json response, how would jsp be aware of that!

Setting the values of fields on success of ajax(), before opening the pop up call was the way out:

$.ajax({

type: "GET",

url : '/site/loadUserData.action?userName ='+userName,

success: function(data){

showProfile(data.profileVO);

  }

 });

function showProfile(profileVO){

  $("#fullName").val(profileVO.fullName);

}


Happy ajaxing & struting(strutting ;) ).


Sunday, 30 June 2013

Spring Data - REST

Gone are the days when people used to take significant amount of time to expose REST service APIs for their domain objects. "SPRING DATA - REST" project is under active development to make your life easy. Its 1.0.0.RC3 version was released on Sep 14, 2012. We can expect the final build to be released soon.

The goal of this project is to expose CRUD operations on JPA entities in the form of REST services.

You can focus on defining your domain classes and SPRING DATA - REST framework will do the job of exposing them in the form of REST services (In simple words you don’t have to write even a single line of code to achieve this.) It is just a matter of configuring your project rightly with the framework.

Here are few simple steps to get started with.

Step 1 :

Add the following maven dependency in your pom.xml :

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-rest-webmvc</artifactId>
  <version>1.0.0.RC3</version>
</dependency>

Use the following repository to resolve this dependency :

<repository>
  <id>spring-milestone</id>
  <name>Spring Maven MILESTONE Repository</name>
  <url>http://repo.springsource.org/libs-milestone</url>
</repository>

Step 2 :

Add RepositoryRestExporterServlet in your web.xml which will act as an exporter for your JPA repositories :

<servlet>
 <servlet-name>exporter</servlet-name>
 <servlet-class>org.springframework.data.rest.webmvc.RepositoryRestExporterServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet> 

<servlet-mapping>
 <servlet-name>exporter</servlet-name>
 <url-pattern>/*</url-pattern>
</servlet-mapping>

Step 3 :

No change is needed in your Spring JPA config file. Here is my config file for your reference :


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:jpa="http://www.springframework.org/schema/data/jpa"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd         http://www.springframework.org/schema/tx
 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd
 http://www.springframework.org/schema/data/jpa
 http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

<context:property-placeholder location="classpath*:*.properties" />
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${database.driverClassName}"/>
        <property name="url" value="${database.url}"/>
        <property name="username" value="${database.username}"/>
        <property name="password" value="${database.password}"/>
</bean>  

<bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <property name="packagesToScan" value="com.viracct.rest.demo" />
 <property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
 <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
     <property name="showSql" value="${hibernate.showSql}" />
     <property name="generateDdl" value="true" />
        </bean>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
 <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<jpa:repositories base-package="com.viracct.rest.demo.dao" />

</beans>

Here I have defined some simple JPA entities - Company, Department, Employee.

package com.viracct.rest.demo.domain;

@Entity

public class Company {

 @Id

 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private String name;
 private String description;
 @OneToMany
 private List<Department> departments;

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public List<Department> getDepartments() {
  return departments;
 }

 public void setDepartments(List<Department> departments) {
  this.departments = departments;
 }

}


@Entity

public class Department {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private String name;
 private String description;
 @OneToMany
 private List<Employee> employees;

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public List<Employee> getEmployees() {
  return employees;
 }

 public void setEmployees(List<Employee> employees) {
  this.employees = employees;
 }

}



@Entity

public class Employee {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private Long code;
 private String name;
 private String designation;

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public Long getCode() {
  return code;
 }

 public void setCode(Long code) {
  this.code = code;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDesignation() {
  return designation;
 }

 public void setDesignation(String designation) {
  this.designation = designation;
 }

}

Here are the JPA repositories for the entities mentioned above.

package com.viracct.rest.demo.dao;

public interface CompanyRepository extends JpaRepository {
}

public interface DepartmentRepository extends JpaRepository {
}

public interface EmployeeRepository extends JpaRepository {
}

Once you have deployed this application, you can see the service end points for your entities by hitting the following URL:  http://localhost:8080/restdemo and the output will be :

{
  "links" : [ {
    "rel" : "department",
    "href" : "http://localhost:8080/restdemo/department"
  }, {
    "rel" : "company",
    "href" : "http://localhost:8080/restdemo/company"
  }, {
    "rel" : "employee",
    "href" : "http://localhost:8080/restdemo/employee"
  } ],
  "content" : [ ]
}

You can browse employee objects with the following URL : http://localhost:8080/restdemo/employee and the output will be :


{
  "links" : [ ],
  "content" : [ {
    "links" : [ {
      "rel" : "self",
      "href" : "http://localhost:8080/restdemo/employee/1"
    } ],
    "name" : "Anuja Kumar",
    "designation" : "Software Developer",
    "code" : 100051
  } ],
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 1
  }
}

Similarly you can access department object with id=2 with the following URL : http://localhost:8080/restdemo/department/2 and the output will be :

{
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:8080/restdemo/department/2"
  }, {
    "rel" : "department.Department.employees",
    "href" : "http://localhost:8080/restdemo/department/2/employees"
  } ],
  "description" : "Product Development Team",
  "name" : "Development"
}

Now if you want to access employee with employee-id=1 from department with department-id=2, you can get that using the following URL: http://localhost:8080/restdemo/department/2/employees/1 and the output will be :

{
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:8080/restdemo/employee/1"
  }, {
    "rel" : "department.Department.employees",
    "href" : "http://localhost:8080/restdemo/department/2/employees/1"
  } ],
  "name" : "Anuja Kumar",
  "designation" : "Software Developer",
  "code" : 100051
}

Friday, 28 June 2013

Sharing CSS Properties Between Classes

Very recently I came across a situation where one of the existing CSS class was a perfect fit for it except for its background property. Just because 1 property was unwanted, I thought to override it with 'style' attribute and setting the background with no image. Very straightforward! Despite the simplicity of this solution, I felt to check what is the recommended practice in such scenarios...may be putting needed common features in one class and inheriting from it. I stumbled across the question- Does CSS support inheritance? (I felt stupid for not knowing the answer).
There are tools/frameworks like OOCSS and LESS which do support inheritance. Without any of them, the better approach to my scenario would be to have a css class and write common properties in it. Then repeat the css class and add rest of the properties to it. Here it is:

.oldClass, .newClass{
 common properties go here
}

.old class{
 the extra one goes here e.g. background: url("../images/arrow.png");
}