Open-Source Project
Development Framework
(OSPDF)
Using Spring Framework 4.0.3
Version 1.0
(Release: December, 2015)
National Informatics Centre, UP State Unit, LUCKNOW
Index
1. Chapter-1: Introduction
1.1 Objective
1.2 Why Spring Framework?
1.3 Spring Development Environment
1.4 Spring - MVC Framework
1.5 Spring – Container
1.6 Spring – Configurations
1.7 Spring – Controllers
1.8 Spring – JSP Views
1.9 Spring – Security
2. Chapter-2: OSPDF (Open Source Project Development Framework)
2.1 About OSPDF
2.2 OSPDF Components with appropriate examples
3. Chapter-3: Complete example using the OSPDF Framework
3.1 CRUD (Create, Read, Update and Delete) operations
3.2 Login Authentication
4. Chapter-4: Some useful reading contents
5. Chapter-5: Naming Conventions and Coding Pattern
1. Chapter-1: Introduction
1.1 Objective
To build upon a basic project development framework for NIC, Uttar Pradesh so that
any project development team can develop an application with less effort and in a
structured and efficient manner. The framework shall be used as a basic template for
development of web applications in open source framework. The framework is a
direction and not binding for the development by different groups. It is open for
upgradation and improvement based on the inputs received from various
divisions/groups of NIC and never shall be thought of as a frozen or proprietary
thing.
1.2 Why Spring Framework?
1. Clear separation of roles. Each role — controller, validator, command object,
form object, model object, DispatcherServlet, handler mapping, view resolver,
and so on — can be fulfilled by a specialized object.
2. Powerful and straightforward configuration of both framework and
application classes as JavaBeans. This configuration capability includes easy
referencing across contexts, such as from web controllers to business objects
and validators.
3. Adaptability, non-intrusiveness, and flexibility. Define any controller
method signature you need, possibly using one of the parameter annotations
(such as @RequestParam, @RequestHeader, @PathVariable, and more) for a
given scenario.
4. Reusable business code, no need for duplication. Use existing business
objects as command or form objects instead of mirroring them to extend a
particular framework base class.
5. Customizable binding and validation. Type mismatches as application-level
validation errors that keep the offending value, localized date and number
binding, and so on instead of String-only form objects with manual parsing and
conversion to business objects.
6. Customizable handler mapping and view resolution. Handler mapping
and view resolution strategies range from simple URL-based configuration, to
sophisticated, purpose-built resolution strategies. Spring is more flexible than
web MVC frameworks that mandate a particular technique.
7. Flexible model transfer. Model transfer with a name/value Map supports
easy integration with any view technology.
8. Customizable locale, time zone and theme resolution, support for JSPs
with or without Spring tag library, support for JSTL, support for Velocity
without the need for extra bridges, and so on.
9. A simple yet powerful JSP tag library known as the Spring tag library that
provides support for features such as data binding and themes. The custom
tags allow for maximum flexibility in terms of markup code.
10.A JSP form tag library, introduced in Spring 2.0 that makes writing forms in
JSP pages much easier.
11.Beans whose lifecycle is scoped to the current HTTP request or HTTP
Session. This is not a specific feature of Spring MVC itself, but rather of the
WebApplicationContext container(s) that Spring MVC uses.
Spring also includes the followings:
Spring Core Container: This is the base module of Spring and provides spring
containers (BeanFactory and ApplicationContext).
Aspect-oriented programming: enables implementing cross-cutting concerns.
Authentication and authorization: configurable security processes that
support a range of standards, protocols, tools and practices via the Spring
Security sub-project (formerly Acegi Security System for Spring).
Convention over configuration: a rapid application development solution for
Spring-based enterprise applications is offered i
Data access: working with relational database management systems on the
Java platform using JDBC and object-relational mapping tools and with NoSQL
databases
Inversion of control container: configuration of application components and
lifecycle management of Java objects, done mainly via dependency injection
Messaging: configurative registration of message listener objects for
transparent message-consumption from message queues via JMS, improvement
of message sending over standard JMS APIs
Model–view–controller: an HTTP- and serve-based framework providing
hooks for extension and customization for web applications and RESTful Web
services.
Remote access framework: configurative RPC-style marshalling of Java
objects over networks supporting RMI, CORBA and HTTP-based protocols
including Web services (SOAP)
Transaction management: unifies several transaction management APIs and
coordinates transactions for Java objects
Remote management: configurative exposure and management of Java
objects for local or remote configuration via JMX
Testing: support classes for writing unit tests and integration tests
1.3 Development Environment
IDE
Eclipse: Eclipse is an integrated development environment (IDE) for Java and
other programming languages like C, C++, PHP, and Ruby etc. Development
environment provided by Eclipse includes the Eclipse Java development tools
(JDT) for Java, Eclipse CDT for C/C++, and Eclipse PDT for PHP, among others.
Application Server
JBoss AS 7.1: The JBoss applications server is a J2EE platform for developing
and deploying enterprise Java applications, Web applications and services, and
portals. J2EE allows the use of standardized modular components and enables
the Java platform to handle many aspects of programming automatically.
Database
PostgreSQL 9.4: PostgreSQL is a powerful, open source object-relational
database system. It has more than 15 years of active development and a
proven architecture that has earned it a strong reputation for reliability, data
integrity, and correctness. PostgreSQL runs on all major operating systems,
including Linux, UNIX (AIX, BSD, HP-UX, SGI IRIX, Mac OS X, Solaris, Tru64),
and Windows.
Development Framework
Spring 4.0.3: Spring is a lightweight framework. The Spring framework
comprises several modules such as IOC, AOP, DAO, Context, ORM, WEB MVC
etc
Entity Framework
Hibernate 4.0.1: Hibernate is a high-performance Object/Relational
persistence and query service which is licensed under the open source GNU
Lesser General Public License (LGPL) and is free to download. Hibernate not
only takes care of the mapping from Java classes to database tables (and from
Java data types to SQL data types), but also provides data query and retrieval
facilities.
1.4 Spring - MVC Framework
MVC stands for – “Model, View and Controller”. It is a design pattern that
separates the business logic, presentation logic and data.
Spring MVC is the web component of Spring’s framework. It provides a rich
functionality for building robust Web Applications. The Spring MVC Framework
is architected and designed in such a way that every piece of logic and
functionality is highly configurable. Also Spring can integrate effortlessly with
other popular Web Frameworks like Struts, WebWork, Java Server Faces and
Tapestry. It means that you can even instruct Spring to use any one of the
Web Frameworks. More than that Spring is not tightly coupled with Servlets or
JSP to render the View to the Clients.
The Spring Web model-view-controller (MVC) framework is designed around a
DispatcherServlet that handles all the HTTP requests and responses. The
request processing workflow of the Spring Web MVC DispatcherServlet is
illustrated in the following diagram:
Following is the sequence of events corresponding to an incoming HTTP request
to DispatcherServlet:
After receiving an HTTP request, DispatcherServlet consults the HandlerMapping to call the appropriate Controller.
The Controller takes the request and calls the appropriate service methods based on used GET or POST method. The service method will set model data
based on defined business logic and returns view name to the DispatcherServlet.
The DispatcherServlet will take help from ViewResolver to pickup the defined
view for the request. Once view is finalized, The DispatcherServlet passes the model data to the view
which is finally rendered on the browser.
All the above mentioned components ie. HandlerMapping, Controller and ViewResolver are parts of WebApplicationContext which is an extension of the
plain ApplicationContext with some extra features necessary for web applications.
1.5 Spring - Container
The Spring container is at the core of the Spring Framework. The
container will create the objects, wire them together, configure them, and manage their complete lifecycle from creation till destruction. The spring container uses dependency injection (DI) to manage the components that
make up an application. These objects are called Spring Beans.
The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata provided. The configuration
metadata can be represented either by XML, Java annotations, or Java code. The following diagram is a high-level view of how Spring works. The Spring IoC container makes use of Java POJO classes and configuration metadata to
produce a fully configured and executable system or application.
Spring provides following two distinct types of containers.
Spring BeanFactory Container
This is the simplest container providing basic support for DI and defined by
the org.springframework.beans.factory.BeanFactoryinterface. The
BeanFactory and related interfaces, such as BeanFactoryAware,
InitializingBean, DisposableBean, are still present in Spring for the purposes of
backward compatibility with the large number of third-party frameworks that
integrate with Spring.
Spring ApplicationContext Container
This container adds more enterprise-specific functionality such as the ability to
resolve textual messages from a properties file and the ability to publish
application events to interested event listeners.
This container is defined by the
org.springframework.context.ApplicationContext interface.
Spring Bean: A Spring Container managed java class is nothing but a Spring Bean.
Java class configured in Spring Bean configuration file
It is a POJO (Plain Old Java Object) class.
Any java class is said to be a POJO if it is not inherting from any
framework specific or technology specific interface or class.
Spring Container controls the life cycle of a component (Spring bean).
Life cycle phases of a Spring Bean:
A Spring bean has 4 life cycle phases.
Instantiation phase
Initialization phase
Ready-To-Use phase
Destruction phase
Instantiation phase: Spring container loads Spring Bean (Java class configured in Bean configuration file) into memory.
Spring container creates the instance of the bean.
Spring container populates bean fields implicitly based on the
configuration specified in configuration file (XML file).
Initialization phase:
Spring container invokes the custom initialization (init) method if any, of the spring bean.
Custom initialization method is any user defined method implemented in Spring bean class and specified in configuration file.
If any resources required for the spring bean, spring developer will
provide them to the spring bean through this initialization method.
Ready-To-Use phase:
After instantiating and initializing the spring bean, Spring container dispenses it to its user. Then it is said to be Ready-To-Use phase.
Destruction phase:
Spring container invokes the custom destroy method if any, of the spring bean.
Custom destroy method is any user defined method implemented in Spring bean class and specified in configuration file.
If any resources given to the spring bean during its initialization phase
are released in this user defined method.
1.6 Spring - Configurations
You need to map requests that you want the DispatcherServlet to handle, by
using a URL mapping in the web.xml file. The following is an example to show
declaration and mapping for spring DispatcherServlet example:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Archetype Created Web Application</display-name> <welcome-file-list>
<welcome-file>/WEB-INF/index.jsp</welcome-file> </welcome-file-list>
<servlet> <servlet-name>spring</servlet-name> <servlet-class>
org.springframework.web.servlet.DispatcherServlet </servlet-class>
<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping>
<servlet-name>spring</servlet-name> <url-pattern>/</url-pattern>
</servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value> </context-param>
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-
class> </listener>
</web-app>
The web.xml file will be kept WebContent/WEB-INF directory of your web
application. OK, upon initialization of spring DispatcherServlet, the framework
will try to load the application context from a file named [servlet-name]-servlet.xml located in the application's WebContent/WEB-INF directory. In this case our file will be spring-servlet.xml.
Next, <servlet-mapping> tag indicates what URLs will be handled by the which
DispatcherServlet. Here all the HTTP requests ending with .jsp will be handled by the spring DispatcherServlet.
If you do not want to go with default filename as [servlet-name]-servlet.xml
and default location as WebContent/WEB-INF, you can customize this file name and location by adding the servlet listener ContextLoaderListener in your
web.xml file as follows:
<web-app...> <!-------- DispatcherServlet definition goes here----->
.... <context-param>
<param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-servlet.xml</param-value> </context-param>
<listener> <listener-
class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> </web-app>
Now, let us check the required configuration for spring-servlet.xml file,
placed in your web application's WebContent/WEB-INF directory:
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven /> <!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory --> <resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <beans:property name="prefix" value="/WEB-INF/view/" />
<beans:property name="suffix" value=".jsp" /> </beans:bean>
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"> <beans:property name="driverClassName" value="org.postgresql.Driver" />
<beans:property name="url" value="jdbc:postgresql://localhost:5432/budgetn" />
<beans:property name="username" value="postgres" /> <beans:property name="password" value="nic123" /> </beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition --> <beans:bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <beans:property name="dataSource" ref="dataSource" /> <beans:property name="annotatedClasses">
<beans:list> <beans:value>com.nic.budget.entity.Person</beans:value>
</beans:list> </beans:property> <beans:property name="hibernateProperties">
<beans:props> <beans:prop
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect </beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop> </beans:props>
</beans:property> </beans:bean>
<beans:bean id="personDAO" class="com.nic.budget.dao.PersonDAOImpl">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</beans:bean> <beans:bean id="personService" class="com.nic.budget.service.PersonServiceImpl">
<beans:property name="personDAO" ref="personDAO"></beans:property>
</beans:bean> <context:component-scan base-package="com.nic.budget.controller" /> <context:component-scan base-package="com.nic.budget.dao" />
<context:component-scan base-package="com.nic.budget.service" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <beans:property name="sessionFactory"
ref="hibernate4AnnotatedSessionFactory" /> </beans:bean>
</beans:beans>
Following are the important points about spring-servlet.xml file:
The [servlet-name]-servlet.xml file will be used to create the beans defined, overriding the definitions of any beans defined with the same name in the
global scope. The <context:component-scan...> tag will be use to activate Spring MVC
annotation scanning capability which allows to make use of annotations like
@Controller and @RequestMapping etc. The InternalResourceViewResolver will have rules defined to resolve the view
names. As per the above defined rule, a logical view named persons is delegated to a view implementation located at /WEB-INF/jsp/person.jsp .
Next section will show you how to create your actual components ie.
Controller, Model and View.
1.7 Spring - Controllers
DispatcherServlet delegates the request to the controllers to execute the functionality specific to it. The @Controller annotation indicates that a
particular class serves the role of a controller. The @RequestMapping annotation is used to map a URL to either an entire class or a particular handler method.
@Controller
public class PersonController {
private PersonService personService;
@Autowired(required=true) @Qualifier(value="personService") public void setPersonService(PersonService ps){
this.personService = ps; }
@RequestMapping(value = "/persons", method = RequestMethod.GET)
public String listPersons(@ModelAttribute("person") PersonDTO p,Model
model) { model.addAttribute("person", new PersonDTO());
model.addAttribute("listPersons", this.personService.listPersons()); return "person";
} }
The @Controller annotation defines the class as a Spring MVC controller. Here, the first usage of @RequestMapping indicates that all handling methods on this controller are relative to the /persons path. Next annotation
@RequestMapping(method = RequestMethod.GET) is used to declare the listpersons() method as the controller's default service method to handle HTTP
GET request. You can define another method to handle any POST request at the same URL.
The value attribute indicates the URL to which the handler method is mapped and the method attribute defines the service method to handle HTTP GET
request. There are following important points to be noted about the controller defined above:
We need to define the business logic inside a service method (PersonService).
We can call another method inside this method as per requirement. Based on the business logic defined, we will create a model within this method.
You can setter different model attributes and these attributes will be accessed by the view to present the final result. This example creates a model with its attribute "message".
A defined service method can return a String which contains the name of the view to be used to render the model. This example returns "person" as logical
view name and as defined in the view-resolver “person.jsp” page will automatically be called.
1.8 Spring – JSP Views
Spring MVC supports many types of views for different presentation technologies. These include - JSPs, HTML, PDF, Excel worksheets, XML, Velocity templates, XSLT, JSON, Atom and RSS feeds, JasperReports etc. But most
commonly we use JSP templates written with JSTL. We now write a simple person view in /WEB-INF/view/person.jsp:
For adding a person
<h1> Add a Person </h1>
<c:url var="addAction" value="/person/add" ></c:url>
<form:form action="/NICBudgetWebApp/person/add" method="Post" commandName="person">
<table> <c:if test="${!empty person.name}">
<tr> <td> <form:label path="id">
<spring:message text="ID"/> </form:label>
</td> <td> <form:input path="id" readonly="true" size="8" disabled="true" />
<form:hidden path="id" /> </td>
</tr> </c:if> <tr>
<td> <form:label path="name">
<spring:message text="Name"/> </form:label> </td>
<td> <form:input path="name" />
</td> </tr> <tr>
<td> <form:label path="country">
<spring:message text="Country"/> </form:label>
</td> <td> <form:input path="country" />
</td> </tr>
<tr> <td colspan="2"> <c:if test="${!empty person.name}">
<input type="submit" value="<spring:message text="Edit Person"/>" />
</c:if> <c:if test="${empty person.name}"> <input type="submit"
value="<spring:message text="Add Person"/>" /> </c:if>
</td> </tr>
</table> </form:form>
Here ${message} is the attribute which we have setup inside the Controller. You can have multiple attributes to be displayed inside your view.
1.9 Spring – Security
It's a java based security solution. It is mostly applicable for the Java based
web applications that are building upon Spring framework. It provides a
comprehensive security services for J2EE based enterprise software applications.
It's very powerful and has a lot more flexibility. We can plug-in the spring
security service to your application very easily.
Authentication and Authorization are two main operations are included in
Spring Security.
1. Authentication is something that asks the user to provide valid credentials to
login to the application.
2. Authorization means validating what role(s) or privilege(s) does the login user
has for this application. Based on which the user will be allowed to access the
different controls or functionality in the application.
So on a whole Authentication validates the identity of a user; if the identity is
authenticated then it is used to decide the authorization of the user.
We need to download the spring security dependency jars. Below are the 3 basic
jars that need to be downloaded, which can perform spring-security for basic
authentication and web application authentication.
1. spring-security-config-3.2.7-RELEASE.jar
2. spring-security-core-3.2-RELEASE .jar
3. spring-security-web-3.2-RELEASE .jar
Web.xml Configuration:
In order to enable spring security for your web application, you have to add
below filter declaration in your web.xml.
<filter>
<filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter>
<filter-mapping> <filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern> </filter-mapping>
All requests now will go through “springSecurityFilterChain” filter which will
apply app security.
spring-servlet.xml Configuration:
As Spring security is enabled till now we can now configure the security XML for different security related options like “Authentication Model”, Login page,
Access denied page etc..
Namespace
Namespace configuration allows you to supplement the traditional Spring beans application context syntax with elements from additional XML schema. In order to use security namespace in application context, “spring-security-config” jar
needs to be in classpath. Schema declaration that needs to be there in “application-context” XML.
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> ...
</beans:beans>
With this configuration we can use “security” as the default namespace rather
than “beans”.
Spring 3.x Security Features:
Spring 3.x Security Framework provides the following Features:
Authentication and Authorization.
Supports BASIC,Digest and Form-Based Authentication.
Supports LDAP Authentication.
Supports OpenID Authentication.
Supports SSO (Single Sign-On) Implementation.
Supports Cross-Site Request Forgery (CSRF) Implementation.
Supports “Remember-Me” Feature through HTTP Cookies.
Supports Implementation of ACLs
Supports “Channel Security” that means automatically switching between
HTTP and HTTPS.
Supports I18N (Internationalization).
Supports JAAS (Java Authentication and Authorization Service).
Supports Flow Authorization using Spring WebFlow Framework.
Supports WS-Security using Spring Web Services.
Supports Both XML Configuration and Annotations. Very Less or minimal
XML Configuration.
Spring 4.x Security Framework supports the following New Features:
Supports WebSocket Security.
Supports Spring Data Integration.
CSRF Token Argument Resolver.
Spring 4 Security Sub-Modules:
Spring 4 Security Module is again divided into 11 sub-modules. It has the
following sub-modules: Spring Security Core Module Spring Security Configuration Module
Spring Security Web Module Spring Security Tag Library Module Spring Security AspectJ Module
Spring Security ACL Module Spring Security LDAP Module
Spring Security OpenID Module Spring Security CAS Module Spring Security Cryptography Module
Spring Security Remoting Module
To support these 11 Spring Security modules, Spring framework has the following
jars:
spring-security-core-4.0.2.RELEASE.jar
spring-security-config-4.0.2.RELEASE.jar
spring-security-web-4.0.2.RELEASE.jar
spring-security-taglibs-4.0.2.RELEASE.jar
spring-security-aspects-4.0.2.RELEASE.jar
spring-security-acl-4.0.2.RELEASE.jar
spring-security-ldap-4.0.2.RELEASE.jar
spring-security-openid-4.0.2.RELEASE.jar
spring-security-cas-4.0.2.RELEASE.jar
spring-security-crypto-4.0.2.RELEASE.jar
spring-security-remoting-4.0.2.RELEASE.jar
Chapter-2: Open Source Project Development
Framework (OSPDF)
2.1 About OSPDF
So far we have discussed about the Spring Framework architecture, the Spring
Cofigurations, the Spring Controllers and the Views. Now we shall discuss
about the details of our Open-Source Project Development Framework and its
components.
Why we require the OSPDF framework?
We want a definite road map to be followed by all NIC, UP State Unit
people so that there is a defined, well-versed development pattern
which not only remains easy to develop applications but also easy to
understand and modify by anyone and everyone,
The framework may help everyone to get some ready to use utility
functions which everyone requires for development to maintain
sessions, apply security to the codes etc.
Since there will be uniform and similar development pattern, if required,
other groups may quickly understand and adopt the coding structure to
build upon a new application in a very less time i.e. it will help in rapid
application development,
As OSPDF will be used as a basic structure by everyone, the problem
resolved by one team shall be helpful to others in resolving theirs. Every
team shall not have to invent or discover to resolve the problems,
New technology updates shall be built in within the framework from time
to time and shall be intimated to everyone using this framework.
Through this every one of us shall get updated in knowing and using the
latest Open-source developments being done elsewhere.
2.2 OSPDF Components
OSPDF (Open Source Project Development Framework) shall have the
following basic components:-
Fig-1 : OSPDF Project Architecture
Utility Class
for
Authentications,
validations,
conversions etc.
User Request (request URL)
DispatcherServlet
(Front Controller)
HandlerMapping
PersonController
[stores form entries to DTO]
through PersonService(DTO)
PersonService
[Converts DTO to Entity for
WRITE and Entity to DTO for
READ]
calls PersonDAO(Entity)
PersonDAO
Calls GenericDAO for CRUD
operations using Hibernate.
Response back to User
4. The Controllers:
For every view we shall be using a dedicated controller.
The role of the Controller is an important one as it overall controls the flow
of the entire project. We can see from the project life-cycle in the previous
section (ref. Spring – Controller), that when a user request is received, the
DispatcherServlet shall consult the HandlerMapping to call the
appropriate Controller. The Controller calls the appropriate service
methods based on used GET or POST method. The Service methods will
set up the model data based on the business logic and returns the view
name to the DispatcherServlet. The DispatcherServlet will take help
from ViewResolver to pickup the defined view for the request. The model
data will be then rendered over to the selected view.
5. Views:
Views are the pages visible to the users over the browser. As stated, the
views are requested by the users to be rendered depending on the URL
written in the browser. In spring, we have many times told that the
DispatcherServlet decides through the Controller that which page is to be
rendered to the client for viewing.
For example a user types,
http://localhost/NICBudgetWebApp/persons
Then the DispatcherServlet shall sends the request to
PersonController.java
@RequestMapping(value = "/persons", method = RequestMethod.GET) public String listPersons(@ModelAttribute("person") PersonDTO p,Model
model)
model.addAttribute("person", new PersonDTO()); model.addAttribute("listPersons", this.personService.listPersons());
return "person"; }
Above Annotation in the Controller shows the request value to be typed by the user. The requested method can be GET or POST.
6. The DTOs (Data Transfer Objects):
DTO (Data Transfer Objects) are simple POJOs for the purpose of
transporting data around between software sub-system interfaces. The
DTOs do not have any behavior other than storage and retrieval of its data.
In simple terms, for Writing to the database, DTO shall get the View data
in its container and pass on to the Entities for database storage through
DAO (Data Access Object). Similarly in case of Read, the Entity will get the
data from the database through DAO and after conversion of the Entity to
DTO; the data will reach the View page.
public class PersonDTO {
private int id;
private String name;
private String country;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
In this instance they are strings as there is no need to describe the data,
or do anything complex with the data in a DTO. This would be passed
through either the webservices or the remote interfaces to the business
logic tier where it would be converted into a value object.
7. The Service Layer:
The service layer takes data transfer objects (and basic types) as method
parameters. It can handle domain model objects but it can return only
data transfer objects back to the web layer.
The service layers delegates the actual verification and database call to the
DAO layer. We inject the Datasource into the PersonDAO implementation.
@Service public class PersonServiceImpl implements PersonService {
private PersonDAO personDAO ;
public PersonDAO getpersonDAO() { return personDAO; }
public void setpersonDAO(PersonDAO personDAO) { this.personDAO = personDAO;
} @Override
@Transactional public void addPerson(Person p) {
// this.personDAO.addPerson(p); this.personDAO.add(p); }
@Override
@Transactional public void updatePerson(Person p) { // this.personDAO.updatePerson(p);
this.personDAO.update(p); }
@Override
@Transactional public List<Person> listPersons() { // return this.personDAO.listPersons();
return this.personDAO.getAll(); }
8. The DAO (Data Access Objects):
The Data Access Object or DAO design pattern is way to reduce coupling
between Business logic and Persistence logic. Application business logic
often needs domain objects which are persisted in either Database or File
System or any other persistence storage. DAO pattern allows you
to encapsulate code for performing CRUD operation against persistence
from rest of application. Which means any change on persistence logic will
not affect other layers of application which is already tested. DAO pattern
enables application to cope with any change in database provider or
persistence technology. In next section we will what are the main benefits
of using DAO design pattern in Java application.
As said earlier that the service layers delegates the actual verification and
database call to the DAO layer. We inject the Datasource into
the PersonDAO implementation. The datasource is defined in the xml from
where it is injected into the DAO. We can also configure to use Hibernate
and JPA.
In the core of Data Access Object or DAO pattern is a Java interface, which
defines various method to perform CRUD operation
e.g. Create, Read, Update and Delete. Based upon your application back-
end technology you can create different implementation of this interface
e.g. JdbcDAOImpl to connect database using JDBC, HibernateDAOImple to
use hibernate or FileDAOImpl. Service layer which uses this Data
Access Object will use interface to interact with Data access layer. We will
make a Generic DAO for common CRUD operations; here is how a typical
Generic DAO Interface looks like:
GenericDAO Interface
public interface GenericDao<E,K> {
public void add(E entity) ; public void saveOrUpdate(E entity) ;
public void update(E entity) ; public void remove(E entity); public void removeById(E entity,Integer id);
public E find(K key); public void delete(K key);
public List<E> getAll() ; }
Now we shall look for the implementation of the above interface using Hibernate,
GenericDAO Implementation
@Repository public abstract class GenericDaoImpl<E, K extends Serializable>
implements GenericDao<E, K> { @Autowired private SessionFactory sessionFactory;
protected Class<? extends E> daoType;
public GenericDaoImpl() { Type t = getClass().getGenericSuperclass(); ParameterizedType pt = (ParameterizedType) t;
daoType = (Class) pt.getActualTypeArguments()[0]; }
protected Session currentSession() { return sessionFactory.getCurrentSession();
}
@Override public void add(E entity) {
currentSession().save(entity); }
@Override public void saveOrUpdate(E entity) {
currentSession().saveOrUpdate(entity); }
For CRUD operations the Generic DAO will be called by all DAOs of specific requirement. Like PersonDAO will call the GenericDAO for all the CRUD
operations by just passing the Person Entity for storing into the database. Interface of PersonDAO
public interface PersonDAO extends GenericDao<Person, Integer>{
public boolean removeAdmin(Integer id); public boolean isAdminRegistered(String userName, String password); public Person getAdmin(String username);
}
Implementation of the above Interface @Repository
public class PersonDAOImpl extends GenericDaoImpl<Person, Integer> implements PersonDAO {
@Override public boolean removeAdmin(Integer id) {
Query employeeTaskQuery = currentSession().createQuery( "from Admin u where :id");
employeeTaskQuery.setParameter("id", id); return employeeTaskQuery.executeUpdate() > 0;
}
9. The Entity class:
An entity is a lightweight persistence domain object. Typically, an entity
represents a table in a relational database, and each entity instance corresponds to a row in that table. The primary programming artifact of an entity is the entity class, although entities can use helper classes.
The persistent state of an entity is represented through either persistent fields or persistent properties. These fields or properties use object/relational mapping annotations to map the entities and entity
relationships to the relational data in the underlying data store.
@Entity @Table(name="PERSON")
public class Person { @Id
@Column(name="id") @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id; private String name;
private String country;
public int getId() { return id;
}
public void setId(int id) { this.id = id;
}
10.The Utility class:
There are certain common functions which every project need to have. These functions include login authentications, validations of data types,
regular expressions to check e-mails/mobiles/PAN Cards and many more.
Since it will be required in all projects we have kept them separately in Utility class.
11.The Configuration files:
web.xml
The /WEB-INF/web.xml file is used to define how to deploy the web module to a Servlet container like JBoss, Tomcat, Glassfish or any other
servlet container. It’s defined by Sun since Java 1.4 ( or 1.2? not so sure) and part of the Java Servlet specification. The file name and locations can not be changed.
Basically web.xml tell container all servlets in the web application with
<servlet> element , then tell container when to use which servlet by the url mapping with <servlet-mapping> element.
In Spring MVC project, for most cast, there is only one servlet
org.springframework.web.servlet.DispatcherServlet. Let this DispatcherServlet handle all the requests. After container hands over
the request to DispatcherServlet, the income http request formally enters the Spring world. A controller will be chosen to handle the request according to @RequestMapping.
Apart from web.xml file, the spring application has two types of context
configuration files for Spring MVC module:
1. ApplicationContext (default name for this file is applicationContext.xml)
2. WebApplicationContext (default name for this file is xxx-
servlet.xml where xxx is the DispatcherServlet name in web.xml)
ApplicationContext
applicationContext.xml is the root context configuration for every web application.
Spring loads applicationContext.xml file and creates the
ApplicationContext for the whole application. There will be only one application context per web application.
If you are not explicitly declaring the context configuration file name in web.xml using the contextConfigLocation param, Spring will search for the applicationContext.xml under WEB-INF folder and throw
FileNotFoundException if it could not find this file.
WebApplicationContext
Apart from ApplicationContext, there can be multiple WebApplicationContext in a single web application.
In simple words, each DispatcherServlet associated with single WebApplicationContext.
xxx-servlet.xml file is specific to the DispatcherServlet and a web application can have more than one DispatcherServlet configured to
handle the requests. In such scenrios, each DispatcherServlet would have a separate xxx-
servlet.xml configured. But, applicationContext.xml will be common
for all the servlet configuration files. Spring will by default load file named “xxx-servlet.xml” from your
webapps WEB-INF folder where xxx is the servlet name in web.xml. If you want to change the name of that file name or change the
location, add initi-param with contextConfigLocation as param name.
Now we shall discuss the details of the configuration files,
1. Web.xml
(i) Servlet information: The following servlet information is mentioned in the web.xml file, <servlet> <servlet-name>spring</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet>
(ii) Servlet mapping information: The details of servlet-mapping information is as follows: <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </servlet>
(iii) Context param information: The details of context-param
information. If this parameter is not configured then applicationContent.xml will be searched by the spring. <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-servlet.xml</param-value> </context-param>
(iv) Listener information: We need to tell the web application that
Spring will be sticking its nose into the HttpServletRequest object, and through that, the HttpSession object as well. For that a
RequestContextListener entry is required. We also need to configure a special ContextLoadListener so that access to the
beanFactory can be mitigated through the ServletContext. <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
2. applicationContext.xml
Spring lets you define multiple contexts in a parent-child hierarchy.
The applicationContext.xml defines the beans for the "root
webapp context", i.e. the context associated with the webapp.
The spring-servlet.xml (or whatever else you call it) defines the beans for one servlet's app context. There can be many of these in a
webapp, one per Spring servlet (e.g. spring1-servlet.xml for servlet spring1, spring2-servlet.xml for servlet spring2).
Beans in spring-servlet.xml can reference beans in applicationContext.xml, but not vice versa.
All Spring MVC controllers must go in the spring-servlet.xml
context.
The application-context.xml can optionally be included when
using Spring MVC or any other framework for that matter. This gives
us a container that may be used to configure other types of spring
beans that provide support for things like data persistence. Basically,
in this configuration file is where we pull in all of the other goodies
Spring offers.
3. spring-servlet.xml
The spring-servlet.xml file contains our entire configuration for
Spring MVC. So in it we will find beans such as
ViewHandlerResolvers, ConverterFactories, Interceptors and so forth.
All of these beans are part of Spring MVC which is a framework that
structures how we handle web requests, providing useful features
such as databinding, view resolution and request mapping.
(i) viewResolve entries
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-
3.0.xsd">
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewReso
lver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
(ii) Security - CustomAuthentication provider entries
<security:authentication-manager>
<security:authentication-provider
ref="customAuthenticationProvider"/>
</security:authentication-manager>
(iii) Security - form-login entries
<security:http auto-config="true">
<security:form-login
login-page="/login"
login-processing-url="/dologin"
default-target-url="/usr"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
<security:logout logout-success-url="/login?logout" />
</security:http>
(iv) Message bean entries
<beans:bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundle
MessageSource">
<beans:property name="basename" value="classpath:messages"
/>
<beans:property name="defaultEncoding" value="UTF-8" />
</beans:bean>
(v) JDBC datasource properties
<beans:bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderCo
nfigurer"
p:location="/WEB-INF/jdbc.properties" />
<beans:bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-
method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
p:password="${jdbc.password}" />
(vi) Hibernate entries
<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.nic.budget.entity.Person</beans:value>
<beans:value>com.nic.budget.entity.Users</beans:value>
<beans:value>com.nic.budget.entity.User</beans:value>
<beans:value>com.nic.budget.entity.UserRoles</beans:value>
<beans:value>com.nic.budget.entity.Role</beans:value>
<beans:value>com.nic.budget.entity.Survey</beans:value>
<beans:value>com.nic.budget.entity.Question</beans:value>
<beans:value>com.nic.budget.entity.Answer</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop
key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
(vii) Component-scan declaration
context:component-scan element in the spring configuration file would eliminate the need for declaring all the beans in the
XML files.
The above declaration in the spring application configuration file would scan the classes inside the specified package and
create the beans instance. Note that it could create beans only if that class is annotated with correct annotations. The
following are the annotations scanned by this element:
@Component @Repository
@Service
@Controller
One advantage of this element is that it also resolve @Autowired and @Qualifier annotations. Therefore if you declare
<context:component-scan>, is not necessary anymore declare <context:annotation-config> too.
<context:component-scan base-package="com.nic.budget" />
4. jdbc.properties
jdbc.driverClassName=org.postgresql.Driver
jdbc.dialect=org.hibernate.dialect.PostgreSQLDialect jdbc.databaseurl=jdbc:postgresql://localhost:5432/budget jdbc.username=postgres
jdbc.password=xxxx
12. Login Authentication:
There are two ways of login authentication,
1. Spring's Default Authentication modal using xml Configuration
2. Spring's Custom Authentication modal that gives a developer an easy
way to customize login according to project's requirement
for example : If we want to authenticate a User using Salted MD5 where
each time a random number is required to generate while login and same is
used for authentication that is not possible with Default Authentication
although it is still Robust , but we can use Custom Authentication to
implement Salted MD5.
We have defined and described all the XML parameters files as well as the
layered java code packages in the above example. Now we shall just
elaborate the places in the project where we need to update for Login
Authentication.
1. Spring's Default Authentication modal
<security:authentication-provider> <security:password-encoder hash="md5"/> <security:jdbc-user-service
data-source-ref="dataSource" users-by-username-query="select usernames username,
user password password, 1 enabled from users where username=?" authorities-by-username-query="select username, authority from authorities where username=?" />
</security:authentication-provider>
In Default model we use above configuration and also provide Database
Users and Roles Table Where Spring's Security Module Authenticate a
User. Roles Are Fetched from database and Set to Spring's Principal Class.
After Login We Can get All Roles and Authority Using Principal Class.
2. Spring's Custom Authentication modal
To make our Custom Authentication we need to define a Class as Below-
@Component
public class CustomAuthenticationProvider1 implements
AuthenticationProvider
It Will be a Component Class implementing AuthenticationProvider
Interface that a has a authenticate method which is called be Spring
Security module when one login.
<security:authentication-manager> <security:authentication-provider
ref="customAuthenticationProvider1"/> </security:authentication-manager>
An Example Of CustomAuthenticationProvider1 Class Using Salted MD5.
Above We See a instance only defined between <security:authentication-manager> tag. After referencing it this will work as a Spring Component.
@Component public class CustomAuthenticationProvider1 implements
AuthenticationProvider { @Autowired
private UsersService userService;
@Override public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String fromyear="";
String toyear=""; String partyear="";
String name = authentication.getName(); String password = authentication.getCredentials().testing();
String pass = authentication.getCredentials().toString(); ServletRequestAttributes attr = (ServletRequestAttributes)
RequestContextHolder.currentRequestAttributes(); HttpSession session= attr.getRequest().getSession(true);
LoginUser user = userService.loadUserByUsername(name); String randno = "";
try {
pass = password.substring(password.indexOf('$') + 1,
password.indexOf('^'));
randno = password.substring(password.indexOf('^') + 1, password.indexOf('~'));
fromyear=session.getAttribute("fromyear").toString(); toyear=session.getAttribute("toyear").toString();
partyear=session.getAttribute("partyear").toString();
} catch (Exception e) {
// TODO: handle exception } boolean result = false;
int rand = 0;
rand = CommonImpl.getRandomNo();
LoginDTO dto = new LoginDTO();
dto.setPassword(pass);
dto.setRandno(randno); dto.setLoginname(name);
result = CommonImpl.md5SaltedVerfication(dto, randno);
if (fromyear != null && fromyear.length() > 0 && toyear != null && toyear.length() > 0 && partyear != null && partyear.length() > 0) {
if(!FormValidation.isNumeric(session.getAttribute("fromyear").toString()) || !FormValidation.isNumeric(session.getAttribute("toyear").toString()) ||
!FormValidation.isNumeric(session.getAttribute("partyear").toString()) ){ result=false;
}else if (!result){ result=false; }else{
result=true; }
}else{ result=false;
}
if (result) { List<GrantedAuthority> grantedAuths = new
ArrayList<GrantedAuthority>(); grantedAuths.add(new
SimpleGrantedAuthority("ROLE_USER")); Authentication auth = new UsernamePasswordAuthenticationToken(name,
password, grantedAuths);
return auth; } else {
return null; }
}
@Override public boolean supports(Class<?> arg0) {
return true; }
}
MD5 Implementation
public static String md5Pass(String password){
System.out.println("password inside md 5 "+password); String passwordToHash = password;
String generatedPassword = null; try {
// Create MessageDigest instance for MD5 MessageDigest md = MessageDigest.getInstance("MD5"); //Add password bytes to digest
md.update(passwordToHash.getBytes()); //Get the hash's bytes
byte[] bytes = md.digest(); //This bytes[] has bytes in decimal format; //Convert it to hexadecimal format
StringBuilder sb = new StringBuilder(); for(int i=0; i< bytes.length ;i++)
{
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
} //Get complete hashed password in hex format
generatedPassword = sb.toString(); } catch (NoSuchAlgorithmException e)
{ e.printStackTrace();
}
return generatedPassword; }
Chapter-3: Complete examples using the OSPDF
Framework
Before discussing over the example we shall frame a problem definition, so that
the reader should be able to understand what we are trying to explain in the
example.
Problem Statement
We have thought that in almost all Projects 2 (two) things are of common nature,
5. CRUD (Create, Read, Update and Delete) operations where the data is read
from the database to a form and vice-versa.
6. User login authentication and authorization.
Reason of taking the above 2 (two) issues are because almost in all projects the
data is either accessed (READ) or written over to disk (CREATE, UPDATE &
DELETE) and that too through a secured manner. So in our example we shall
emphasize on the above 2 issues only through demonstrating a simple project
which does all these operations using a single form over browsers.
The form shall be able to show the data of all the persons having three fields, id,
name and country. The table for the persons is created in a POSTGRESQL
database. The same form shall be able to store person data with the operations
for adding new persons, updating existing persons and option for deleting any
person by selecting. For reaching to the form the user should be able to login
through a secured login.
So, in a nutshell the form should be allowing users to do all CRUD operations
through a single interface.
Solution Definition
To achieve the result as mentioned in the problem statement, we shall be
proceeding as follows:-
1. We shall create a table in POSTGRESQL database called ‘person’.
2. Now, in the Eclipse IDE, we shall create a new Dynamic Web Project.
3. We shall attach a server (JBOSS 7.1) to the project and select the appropriate
JRE or JDK.
4. Then we shall configure the web.xml file for defining the spring
dispatcherServlet class and the name of the servlet file. We shall name the
servlet file as ‘spring’. (so we shall make spring-servlet.xml)
5. Now it is time to configure the spring-servlet.xml file for other configuration
parameters,
viewresolver information,
hibernate related information,
beans information,
property definition information, and so on.
6. To define the database configuration parameters and properties, we need to
create a jdbc.properties file,
7. Now it is time to create Controller files. We start by writing the
PersonController.java for the CRUD operation and LoginController.java
for login authentication. The spring container is able to know that it is a
controller by reading the @Controller annotation. Other important
annotations in the controller file such as @RequestMapping,
@ModelAttribute defines the view and the model details.
8. The @RequestMapping annotation (@RequestMapping(value = "/persons", method
= RequestMethod.GET) is used to specify the View pages to be developed in
JSP, hence we create a persons.jsp, to show to the viewer as per the values
returned by the Controller.
9. The @ModelAttribute annotation (public String
listPersons(@ModelAttribute("person") PersonDTO p,Model model), is used to
transfer the form(jsp page) values to the model or the DTO (Data Transfer
Object) for the back-end operations.
10.For getting the back-end data, the Controller will call the
PersonService.java (model.addAttribute("listPersons",
this.personService.listPersons());).
11.The implementation of PersonServiceImpl.java having a listPersons()
method (return this.personDAO.getAll();) will in turn call the PersonDAO for
back-end data read.
12.A GenericDAO.java page is written which contains all CRUD operation
methods. The PersonDAO.java extends to GenericDAO.java for
implementation of CRUD methods. (return
currentSession().createCriteria(daoType).list();). It automatically returns the
list of all persons using the Hibernate class.
13.The GenericDAO uses parameter (public void add(E entity) ;) parameter E for
entity. So there is an entity class Person.java, which is as per table
definition.
14.There is a Utilities package where we need to write the general methods.
The above points give a point-wise solution definition in nutshell of the entire
project.
Solution Description
(1) CRUD operation Example
The following example shows all the CRUD (Create, Read, Update and Delete)
operations for a person. Since we wanted to keep it simple, so only three (3)
fields were taken,
Table Name: PERSON
CREATE TABLE person
(
id serial NOT NULL,
name character varying(20) NOT NULL,
country character varying(20) NOT NULL,
CONSTRAINT person_pkey PRIMARY KEY (id)
)
Please note that the id field is auto-increment field (serial field type) in
POSTGreSQL 9.4.
Now in Eclipse IDE we create a new project of type Dynamic Web Project
type.
We name the project as NICBudgetWebApp.
We configure the Build Path and Project Facet from the properties of the
application.
The Runtime application server to be attached to the project is JBoss 7.1
Runtime.
We shall now work for a common page where you shall be able to,
1. Add a person,
2. Update a person,
3. Delete a person,
4. Display the list of all available persons
For the development of the above page we shall be writing the
configurations, followed by the controller, the view, the DTO, the Entity, the
Services and the DAO.
1. Web.xml
In web.xml we shall configure,
The welcome-file name configuration.
2. The servlet-name configuration.
3. The definition for context parameter name.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Archetype Created Web Application</display-name>
<welcome-file-list> <welcome-file>/WEB-INF/index.jsp</welcome-file>
</welcome-file-list> <servlet> <servlet-name>spring</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet
</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
<servlet-mapping> <servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern> </servlet-mapping>
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-servlet.xml</param-value>
</context-param> <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
</web-app>
2. spring-servlet.xml
In spring-servlet.xml we shall configure,
1. The view-resolver configuration.
2. The datasource configuration for connecting database using user-id
and password.
3. The hibernate datasource definitions for entities etc.
4. The DAO (Data Access Objects), the Services and the Controllers
definitions.
5. The details of the TransactionManagers and SessionFactory.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model --> <annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory --> <resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/view/" /> <beans:property name="suffix" value=".jsp" />
</beans:bean> <beans:bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<beans:property name="driverClassName" value="org.postgresql.Driver" /> <beans:property name="url"
value="jdbc:postgresql://localhost:5432/budget" /> <beans:property name="username" value="postgres" />
<beans:property name="password" value=" postgres" /> </beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition --> <beans:bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <beans:property name="dataSource" ref="dataSource" />
<beans:property name="annotatedClasses"> <beans:list>
<beans:value>com.nic.budget.entity.Person</beans:value> </beans:list>
</beans:property> <beans:property name="hibernateProperties"> <beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect. PostgreSQLDialect
</beans:prop> <beans:prop key="hibernate.show_sql">true</beans:prop> </beans:props>
</beans:property> </beans:bean>
<beans:bean id="personDAO" class="com.nic.budget.dao.PersonDAOImpl"> <beans:property name="sessionFactory"
ref="hibernate4AnnotatedSessionFactory" /> </beans:bean>
<beans:bean id="personService" class="com.nic.budget.service.PersonServiceImpl">
<beans:property name="personDAO" ref="personDAO"></beans:property> </beans:bean>
<context:component-scan base-package="com.nic.budget.controller" /> <context:component-scan base-package="com.nic.budget.dao" />
<context:component-scan base-package="com.nic.budget.service" /> <tx:annotation-driven transaction-manager="transactionManager"/>
<beans:bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
</beans:beans>
3. application-security.xml
Here we have not used this configuration file as all settings have been done in
spring-servlet.xml file.
4. jdbc.properties
This is to define properties related to connection,
jdbc.driverClassName=org.postgresql.Driver
jdbc.dialect=org.hibernate.dialect. PostgreSQLDialect jdbc.databaseurl=jdbc:postgresql://localhost:5432/budget
jdbc.username=postgres jdbc.password=postgres
5. Controller (package name: com.nic.budget.controller)
PersonController.java
package com.nic.budget.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.nic.budget.dto.PersonDTO;
import com.nic.budget.service.PersonService; import com.nic.budget.utilities.ConvertDTO2Entity;
@Controller public class PersonController { private PersonService personService;
@Autowired(required=true) @Qualifier(value="personService")
public void setPersonService(PersonService ps){ this.personService = ps; }
@RequestMapping(value = "/persons", method = RequestMethod.GET)
public String listPersons(@ModelAttribute("person") PersonDTO p,Model model) { model.addAttribute("person", new PersonDTO());
model.addAttribute("listPersons", this.personService.listPersons()); return "person";
} //For add and update person both
@RequestMapping(value= "/person/add", method = RequestMethod.POST)
public String addPerson(@ModelAttribute("person") PersonDTO p,Model model){
if(p.getId() == 0){
//new person, add it this.personService.addPerson(ConvertDTO2Entity.getEntity(p));
}else{ //existing person, call update
this.personService.updatePerson(ConvertDTO2Entity.getEntity(p)); }
model.addAttribute("person", new PersonDTO()); model.addAttribute("listPersons", this.personService.listPersons());
return "person"; }
@RequestMapping("/remove/{id}")
public String removePerson(@PathVariable("id") int id){
this.personService.removePerson(id); return "redirect:/persons"; }
@RequestMapping("/edit/{id}")
public String editPerson(@PathVariable("id") int id, Model model){ model.addAttribute("person", this.personService.getPersonById(id));
//model.addAttribute("person", this.personService.getPersonById(id));
model.addAttribute("listPersons", this.personService.listPersons()); return "person"; }
}
6. Views
All views will be in the “view” folder of WebContent.
person.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ page session="false" %> <html>
<head> <title>Person Page</title>
<style type="text/css"> .tg {border-collapse:collapse;border-spacing:0;border-color:#ccc;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#fff;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-
width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#f0f0f0;} .tg .tg-4eph{background-color:#f9f9f9}
</style> </head>
<body> <h1> Add a Person
</h1>
<c:url var="addAction" value="/person/add" ></c:url>
<form:form action="/NICBudgetWebApp/person/add" method="Post" commandName="person"> <table>
<c:if test="${!empty person.name}"> <tr>
<td> <form:label path="id"> <spring:message text="ID"/>
</form:label> </td>
<td> <form:input path="id" readonly="true" size="8" disabled="true" /> <form:hidden path="id" />
</td> </tr>
</c:if> <tr> <td>
<form:label path="name"> <spring:message text="Name"/>
</form:label> </td> <td>
<form:input path="name" /> </td>
</tr> <tr>
<td> <form:label path="country">
<spring:message text="Country"/> </form:label>
</td> <td> <form:input path="country" />
</td> </tr>
<tr> <td colspan="2"> <c:if test="${!empty person.name}">
<input type="submit" value="<spring:message text="Edit Person"/>" />
</c:if> <c:if test="${empty person.name}"> <input type="submit"
value="<spring:message text="Add Person"/>" /> </c:if>
</td> </tr>
</table> </form:form> <br>
<h3>Persons List</h3> <c:if test="${!empty listPersons}">
<table class="tg"> <tr> <th width="80">Person ID</th>
<th width="120">Person Name</th> <th width="120">Person Country</th>
<th width="60">Edit</th> <th width="60">Delete</th> </tr>
<c:forEach items="${listPersons}" var="person"> <tr>
<td>${person.id}</td> <td>${person.name}</td> <td>${person.country}</td>
<td><a href="<c:url value='/edit/${person.id}' />" >Edit</a></td> <td><a href="<c:url value='/remove/${person.id}' />"
>Delete</a></td> </tr> </c:forEach>
</table> </c:if>
</body> </html>
7. DTO (Data Transfer Object)(package name: com.nic.budget.dto)
Controller gets the page (form) values to be stored in the DTOs.
PersonDTO.java
package com.nic.budget.dto;
public class PersonDTO { private int id; private String name;
private String country; public int getId() {
return id; } public void setId(int id) {
this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name;
} public String getCountry() { return country;
} public void setCountry(String country) {
this.country = country; }
}
8. Entities (package name: com.nic.budget.entity)
Entities are almost the true replicas of the database tables.
Person.java
package com.nic.budget.entity; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table;
@Entity
@Table(name="PERSON") public class Person {
@Id
@Column(name="id") @GeneratedValue(strategy=GenerationType.IDENTITY) private int id;
private String name;
private String country;
public int getId() { return id;
} public void setId(int id) {
this.id = id; }
public String getName() {
return name; }
public void setName(String name) { this.name = name;
} public String getCountry() {
return country; }
public void setCountry(String country) { this.country = country;
}
@Override public String toString(){ return "id="+id+", name="+name+", country="+country;
} }
9. Service Layer (package name: com.nic.budget.service)
The service layer the middle-tier of the application. It gets DTOs and converts
them to the Entities before storing to database tables. While reads it gets Entities from the table and Converts them to DTO before passing to the views
through the Controllers.
PersonService.java [Interface]
package com.nic.budget.service;
import java.util.List; import com.nic.budget.entity.Person;
public interface PersonService { public void addPerson(Person p);
public void updatePerson(Person p); public List<Person> listPersons(); public Person getPersonById(int id);
public void removePerson(int id); }
PersonServiceImpl.java
package com.nic.budget.service;
import java.util.List;
import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.nic.budget.dao.PersonDAO;
import com.nic.budget.entity.Person;
@Service public class PersonServiceImpl implements PersonService { private PersonDAO personDAO ;
public PersonDAO getpersonDAO() { return personDAO;
} public void setpersonDAO(PersonDAO personDAO) { this.personDAO = personDAO;
} @Override
@Transactional public void addPerson(Person p) { // this.personDAO.addPerson(p);
this.personDAO.add(p); }
@Override @Transactional public void updatePerson(Person p) {
// this.personDAO.updatePerson(p); this.personDAO.update(p);
} @Override
@Transactional public List<Person> listPersons() {
// return this.personDAO.listPersons(); return this.personDAO.getAll();
} @Override @Transactional
public Person getPersonById(int id) { // return this.personDAO.getPersonById(id);
return this.personDAO.find(id); } @Override
@Transactional public void removePerson(int id) {
// this.personDAO.removePerson(id); Person p=new Person(); this.personDAO.removeById(p,id);
} }
10. DAO (Data Access Layer) (package name: com.nic.budget.dao)
The DAO layer actually interacts with the database and is the lowest level of the layers. Since all database operations are basically of CRUD type so we have
worked out a Generic DAO which shall be used for performing all CRUD operations for each type of entity.
GenericDAO.java [Interface]
package com.nic.budget.dao;
import java.util.List; public interface GenericDao<E,K> {
public void add(E entity) ; public void saveOrUpdate(E entity) ;
public void update(E entity) ; public void remove(E entity); public void removeById(E entity,Integer id);
public E find(K key); public void delete(K key);
public List<E> getAll() ; }
GenericDAOImpl.java
package com.nic.budget.dao;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.nic.budget.entity.Person; import java.lang.reflect.Type;
import java.util.List; @SuppressWarnings("unchecked")
@Repository public abstract class GenericDaoImpl<E, K extends Serializable> implements GenericDao<E, K> {
@Autowired private SessionFactory sessionFactory;
protected Class<? extends E> daoType;
public GenericDaoImpl() { Type t = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) t; daoType = (Class) pt.getActualTypeArguments()[0];
} protected Session currentSession() {
return sessionFactory.getCurrentSession(); }
@Override public void add(E entity) {
currentSession().save(entity); }
@Override public void saveOrUpdate(E entity) {
currentSession().saveOrUpdate(entity); }
@Override public void update(E entity) {
//currentSession().saveOrUpdate(entity); // this.getCurrentSession().;
Session session = this.sessionFactory.getCurrentSession();
session.update(entity);
} @Override
public void remove(E entity) { currentSession().delete(entity); }
public void removeById(E entity,Integer id) {
// currentSession().delete(id); Session session = this.sessionFactory.getCurrentSession();
if(null != (E) session.load(daoType, new Integer(id))){
session.delete( (E) session.load(daoType, new Integer(id))); } // logger.info("Person deleted successfully, person details="+p);
}
@Override public E find(K key) {
return (E) currentSession().get(daoType, key); }
@Override public void delete(K key) {
currentSession().get(daoType, key); }
@Override public List<E> getAll() {
return currentSession().createCriteria(daoType).list(); }
public SessionFactory getSessionFactory() { return sessionFactory;
} public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory; }
}
PersonDAO.java [Interface]
package com.nic.budget.dao;
import com.nic.budget.entity.Person; public interface PersonDAO extends GenericDao<Person, Integer>{
public boolean removeAdmin(Integer id); public boolean isAdminRegistered(String userName, String password);
public Person getAdmin(String username); }
PersonDAOImpl.java
package com.nic.budget.dao; import org.hibernate.Query;
import org.springframework.stereotype.Repository;
import com.nic.budget.entity.Person;
@Repository public class PersonDAOImpl extends GenericDaoImpl<Person, Integer> implements PersonDAO {
@Override public boolean removeAdmin(Integer id) {
Query employeeTaskQuery = currentSession().createQuery( "from Admin u where :id"); employeeTaskQuery.setParameter("id", id);
return employeeTaskQuery.executeUpdate() > 0; }
@Override public boolean isAdminRegistered(String userName, String password) {
/*You can use any character instead of 'A'. If a record is found, only single character, in this example 'A', will return from database
*/ Query employeeTaskQuery = currentSession().createQuery( "select 'A' from Admin u where username=:username and
password=:password"); employeeTaskQuery.setParameter("username", userName);
employeeTaskQuery.setParameter("password", password); return employeeTaskQuery.list().size() > 0; }
@Override
public Person getAdmin(String username) { Query query = currentSession().createQuery(
"from Admin " + "where username=:username");
query.setParameter("username", username); return (Person) query.uniqueResult();
} }
11. Utilities (package name: com.nic.common.utilities)
The common utilities shall be stored over here.
(2) Login Authentication Example
Now we shall discuss over our 2nd example which is related to Login
authentication which is also a common feature of all web applications.
We shall make 2 tables named User and UserRoles Tabl.
Table Name: Users
CREATE TABLE users
(
id serial NOT NULL,
username character varying(100) NOT NULL,
password character varying(20),
secure_password character varying(200),
enabled boolean,
accountnonexpired boolean,
accountnonlocked boolean
CONSTRAINT usersid1 PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE users
OWNER TO postgres;
Table Name: UserRoles
CREATE TABLE UserRoles
(
user_role_id integer NOT NULL,
username character varying(20),
role character varying(20),
CONSTRAINT user_role_id PRIMARY KEY (user_role_id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE UserRoles
OWNER TO postgres;
1. Web.xml
In web.xml we need not do anything more for further configuration,
2. spring-servlet.xml
In spring-servlet.xml we shall configure (change) the following,
<security:authentication-manager>
<security:authentication-provider ref="customAuthenticationProvider1"/> </security:authentication-manager> customAuthenticationProvider1 is a bean instance used for CustomAuthenticationProvider1 default bean name is converted as class name but starting letter in Small. Bean - customAuthenticationProvider1
3. CustomAuthentication Provider
[CustomAuthenticationProvider1.java]
@Component public class CustomAuthenticationProvider1 implements AuthenticationProvider {
@Autowired
private UsersService userService;
@Override public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String fromyear="";
String toyear=""; String partyear="";
String name = authentication.getName(); String password = authentication.getCredentials().testing();
String pass = authentication.getCredentials().toString(); ServletRequestAttributes attr = (ServletRequestAttributes)
RequestContextHolder.currentRequestAttributes(); HttpSession session= attr.getRequest().getSession(true);
LoginUser user = userService.loadUserByUsername(name); String randno = "";
try {
pass = password.substring(password.indexOf('$') + 1,
password.indexOf('^')); randno = password.substring(password.indexOf('^') + 1, password.indexOf('~'));
fromyear=session.getAttribute("fromyear").toString(); toyear=session.getAttribute("toyear").toString(); partyear=session.getAttribute("partyear").toString();
} catch (Exception e) { // TODO: handle exception
} boolean result = false;
int rand = 0;
rand = CommonImpl.getRandomNo();
LoginDTO dto = new LoginDTO();
dto.setPassword(pass); dto.setRandno(randno);
dto.setLoginname(name);
result = CommonImpl.md5SaltedVerfication(dto, randno); if (fromyear != null && fromyear.length() > 0 && toyear != null
&& toyear.length() > 0 && partyear != null && partyear.length() > 0) {
if(!FormValidation.isNumeric(session.getAttribute("fromyear").toString()
) || !FormValidation.isNumeric(session.getAttribute("toyear").toString()) ||
!FormValidation.isNumeric(session.getAttribute("partyear").toString()) ){ result=false; }else if (!result){
result=false; }else{
result=true; }
}else{
result=false; }
if (result) {
List<GrantedAuthority> grantedAuths = new
ArrayList<GrantedAuthority>(); grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication auth = new UsernamePasswordAuthenticationToken(name,
password, grantedAuths);
return auth; } else {
return null; }
}
@Override public boolean supports(Class<?> arg0) {
return true; } }
4. Controller [LoginController: /login mapping]
A Controller file called LoginController.java will handle the views and
models related to the authentication module. Similar annotations as
mentioned in the above example for @RequestMapping have been used.
// Spring Security see this : @RequestMapping(value = "/login", method =
RequestMethod.GET) public ModelAndView login(@ModelAttribute("log") LoginDTO p,
@RequestParam(value = "error", required = false) String error, @RequestParam(value = "logout", required = false)
String logout) {
ModelAndView model = new ModelAndView();
//#######################Validational Part Start#########################################
#
ServletRequestAttributes attr = (ServletRequestAttributes)
RequestContextHolder.currentRequestAttributes();
HttpSession session= attr.getRequest().getSession(true); String errorFilter="";
if(session.getAttribute("username")!=null &&
session.getAttribute("username").toString().length()>0){ }else{
errorFilter+=" username required!"; }
if(session.getAttribute("password")!=null && session.getAttribute("password").toString().length()>0){
}else{ errorFilter+=" password required!";
} if(session.getAttribute("fromyear")!=null && session.getAttribute("fromyear").toString().length()>0){
if(!FormValidation.isNumeric(session.getAttribute("fromyear").toString()))
errorFilter+=" fromyear Numeric Value Rquired!";
}else{ // errorFilter+=" fromyear required!";
}
if(session.getAttribute("toyear")!=null && session.getAttribute("toyear").toString().length()>0){
if(!FormValidation.isNumeric(session.getAttribute("toyear").toString()))
errorFilter+=" toyear Numeric Value Rquired!";
}else{ // errorFilter+=" toyear required!";
} if(session.getAttribute("partyear")!=null &&
session.getAttribute("partyear").toString().length()>0){
if(!FormValidation.isNumeric(session.getAttribute("partyear").toString()))
errorFilter+=" partyear Numeric Value Rquired!";
}else{
//errorFilter+=" partyear required!"; }
//####################### Validational Part
Ends########################################## if (error != null ) {
model.addObject("error", errorFilter);
session.invalidate(); }
if (logout != null) { model.addObject("msg", "You've been logged out
successfully."); session.invalidate();
} model.setViewName("login");
return model;
}
Chapter-4: Some useful reading contents
4.1 Basic concepts of Spring
The basic philosophy underlying spring framework is to avoid tight coupling between various modules. The advantage of using spring framework is that it
lets the developer concentrate on developing the application while the underlying spring framework takes care of transaction APIs, remote APIs, JMX APIs, JMS APIs.
4.2 Benefits of using Spring Framework
Works on POJOs. Hence easier for dependency injection / injection of test data.
With the Dependency Injection(DI) approach, dependencies are explicit
and evident in constructor or JavaBean properties Enhances modularity. Provides more readable codes.
Provides loose coupling between different modules. Effective in organizing the middle-tier applications. Flexible use of Dependency injection. Can be configured by XML based
schema or annotation-based style. Supports declarative transaction, caching, validation and formatting.
4.2.1 What is IOC (or Dependency Injection)?
The basic concept of the Inversion of Control pattern (also known as dependency injection) is that you do not create your objects but describe
how they should be created. You don't directly connect your components and services together in code but describe which services are needed by
which components in a configuration file. A container (in the case of the Spring framework, the IOC container) is then responsible for hooking it all up.
i.e., Applying IoC, objects are given their dependencies at creation time by
some external entity that coordinates each object in the system. That is, dependencies are injected into objects. So, IoC means an inversion of responsibility with regard to how an object obtains references to
collaborating objects.
4.2.2 What are the different types of IOC (dependency injection) ? Setter Injection (e.g. Spring): Dependencies are assigned through
JavaBeans properties (ex: setter methods).
Interface Injection (e.g. Avalon): Injection is done through an interface. Note: Spring supports only Constructor and Setter Injection
There are three types of dependency injection:
Constructor Injection (e.g. Pico container, Spring etc): Dependencies are provided as constructor parameters.
4.2.3 What are the benefits of IOC (Dependency Injection)?
Benefits of IOC (Dependency Injection) are as follows:
Minimizes the amount of code in your application. With IOC containers you do not care about how services are created and how you get
references to the ones you need. You can also easily add additional services by adding a new constructor or a setter method with little or no extra configuration.
Make your application more testable by not requiring any singletons or
JNDI lookup mechanisms in your unit test cases. IOC containers make unit testing and switching implementations very easy by manually allowing you to inject your own objects into the object under test.
Loose coupling is promoted with minimal effort and least intrusive
mechanism. The factory design pattern is more intrusive because components or services need to be requested explicitly whereas in IOC
the dependency is injected into requesting piece of code. Also some containers promote the design to interfaces not to implementations design concept by encouraging managed objects to implement a well-
defined service interface of your own.
IOC containers support eager instantiation and lazy loading of services. Containers also provide support for instantiation of managed objects, cyclical dependencies, life cycles management, and dependency
resolution between managed objects etc.
4.2.4 What is Spring ? Spring is an open source framework created to address the complexity of
enterprise application development. One of the chief advantages of the Spring framework is its layered architecture, which allows you to be
selective about which of its components you use while also providing a cohesive framework for J2EE application development.
4.2.5 What are the advantages of Spring framework?
The advantages of Spring are as follows:
Spring has layered architecture. Use what you need and leave you don't need now.
Spring Enables POJO Programming. There is no behind the scene magic here. POJO programming enables continuous integration and
testability.
Dependency Injection and Inversion of Control Simplifies JDBC
Open source and no vendor lock-in.
4.2.6 What are features of Spring ?
Lightweight: spring is lightweight when it comes to size and
transparency. The basic version of spring framework is around 1MB.
And the processing overhead is also very negligible. Inversion of control (IOC): Loose coupling is achieved in spring
using the technique Inversion of Control. The objects give their dependencies instead of creating or looking for dependent objects.
Aspect oriented (AOP): Spring supports Aspect oriented
programming and enables cohesive development by separating application business logic from system services.
Container: Spring contains and manages the life cycle and configuration of application objects.
MVC Framework: Spring comes with MVC web application
framework, built on core Spring functionality. This framework is highly configurable via strategy interfaces, and accommodates multiple view
technologies like JSP, Velocity, Tiles, iText, and POI. But other frameworks can be easily used instead of Spring MVC Framework.
Transaction Management: Spring framework provides a generic abstraction layer for transaction management. This allowing the developer to add the pluggable transaction managers, and making it
easy to demarcate transactions without dealing with low-level issues. Spring's transaction support is not tied to J2EE environments and it
can be also used in container less environments. JDBC Exception Handling: The JDBC abstraction layer of the Spring
offers a meaningful exception hierarchy, which simplifies the error
handling strategy. Integration with Hibernate, JDO, and iBATIS: Spring provides best Integration services with Hibernate, JDO and
iBATIS
4.2.7 How many modules are there in Spring? What are they?
Spring comprises of seven modules. They are:
The core container: The core container provides the essential functionality of the Spring framework. A primary component of the
core container is the BeanFactory, an implementation of the Factory pattern. The BeanFactory applies the Inversion of Control (IOC)
pattern to separate an application's configuration and dependency specification from the actual application code.
Spring context: The Spring context is a configuration file that
provides context information to the Spring framework. The Spring context includes enterprise services such as JNDI, EJB, e-mail,
internalization, validation, and scheduling functionality.
Spring AOP: The Spring AOP module integrates aspect-oriented programming functionality directly into the Spring framework, through
its configuration management feature. As a result you can easily AOP-enable any object managed by the Spring framework. The Spring AOP
module provides transaction management services for objects in any Spring-based application. With Spring AOP you can incorporate declarative transaction management into your applications without
relying on EJB components.
Spring DAO: The Spring JDBC DAO abstraction layer offers a
meaningful exception hierarchy for managing the exception handling and error messages thrown by different database vendors. The exception hierarchy simplifies error handling and greatly reduces the
amount of exception code you need to write, such as opening and closing connections. Spring DAO's JDBC-oriented exceptions comply
to its generic DAO exception hierarchy.
Spring ORM: The Spring framework plugs into several ORM frameworks to provide its Object Relational tool, including JDO,
Hibernate, and iBatis SQL Maps. All of these comply to Spring's generic transaction and DAO exception hierarchies.
Spring Web module: The Web context module builds on top of the application context module, providing contexts for Web-based
applications. As a result, the Spring framework supports integration with Jakarta Struts. The Web module also eases the tasks of handling multi-part requests and binding request parameters to domain
objects.
Spring MVC framework: The Model-View-Controller (MVC)
framework is a full-featured MVC implementation for building Web applications. The MVC framework is highly configurable via strategy interfaces and accommodates numerous view technologies including
JSP, Velocity, Tiles, iText, and POI.
4.2.8 What is Bean Factory ? A BeanFactory is like a factory class that contains a collection of beans. The
BeanFactory holds Bean Definitions of multiple beans within itself and then instantiates the bean whenever asked for by clients.
BeanFactory is able to create associations between collaborating
objects as they are instantiated. This removes the burden of
configuration from bean itself and the beans client. BeanFactory also takes part in the life cycle of a bean, making calls to
custom initialization and destruction methods.
4.2.9 What is Application Context?
A bean factory is fine to simple applications, but to take advantage of the
full power of the Spring framework, you may want to move up to Springs
more advanced container, the application context. On the surface, an application context is same as a bean factory.Both load bean definitions,
wire beans together, and dispense beans upon request. But it also provides:
A means for resolving text messages, including support for
internationalization.
A generic way to load file resources. Events to beans that are registered as listeners.
4.2.10 What is the difference between Bean Factory and Application
Context ?
On the surface, an application context is same as a bean factory. But
application context offers much more..
Application contexts provide a means for resolving text messages,
including support for i18n of those messages. Application contexts provide a generic way to load file resources, such
as images. Application contexts can publish events to beans that are registered
as listeners. Certain operations on the container or beans in the container, which
have to be handled in a programmatic fashion with a bean factory,
can be handled declaratively in an application context. ResourceLoader support: Spring’s Resource interface us a flexible
generic abstraction for handling low-level resources. An application context itself is a ResourceLoader, Hence provides an application with access to deployment-specific Resource instances.
MessageSource support: The application context implements MessageSource, an interface used to obtain localized messages, with
the actual implementation being pluggable
Spring feature - Dependency Injection (a nice example by SivaLabs)
Recently our company started developing a new java based web application and
after some evaluation process we decided to use Spring.
But many of the team members are not aware of Spring and Dependency
Injection principles.
So I was asked to give a crash course on what is Dependency Injection and
basics on Spring.
Instead of telling all the theory about IOC/DI I thought of explaining with an
example.
Requirement: We will get some Customer Address and we need to validate the
address. After some evaluation we thought of using Google Address Validation
Service.
Legacy(Bad) Approach:
Just create an AddressVerificationService class and implement the logic.
Assume GoogleAddressVerificationService is a service provided by Google which
takes Address as a String and Return longitude/latitude.
class AddressVerificationService {
public String validateAddress(String address) {
GoogleAddressVerificationService gavs = new GoogleAddressVerificationService(); String result = gavs.validateAddress(address);
return result; }
}
Issues with this approach:
1. If you want to change your Address Verification Service Provider you
need to change the logic.
2. Whenever you need to support a new Service Provider you need to
add/change logic using if-else-if
3. You can't do Unit Test with some Dummy AddressVerificationService
(Using Mock Objects)
Due to some reason Client ask us to support multiple
AddressVerificationService Providers and we need to determine which
service to use at runtime.
To accommodate this you may thought of changing the above class as
below:
class AddressVerificationService {
//This method validates the given address and return longitude/latitude details. public String validateAddress(String address)
{ String result = null;
int serviceCode = 2; // read this code value from a config file
if(serviceCode == 1) {
GoogleAddressVerificationService googleAVS = new GoogleAddressVerificationService();
result = googleAVS.validateAddress(address); } else if(serviceCode == 2) {
YahooAddressVerificationService yahooAVS = new YahooAddressVerificationService();
result = yahooAVS.validateAddress(address); } return result;
} }
IOC/DI Approach:
In the above approaches AddressVerificationService is taking the control of creating its dependencies.
So whenever there is a change in its dependencies the AddressVerificationService
will change. Now let us rewrite the AddressVerificationService using IOC/DI pattern.
class AddressVerificationService
{ private AddressVerificationServiceProvider serviceProvider;
public AddressVerificationService(AddressVerificationServiceProvider serviceProvider) {
this.serviceProvider = serviceProvider; }
public String validateAddress(String address) {
return this.serviceProvider.validateAddress(address); }
} interface AddressVerificationServiceProvider {
public String validateAddress(String address); }
Here we are injecting the AddressVerificationService dependency AddressVerificationServiceProvider.
Now let us implement the AddressVerificationServiceProvider with multiple provider services.
class YahooAVS implements AddressVerificationServiceProvider
{ @Override public String validateAddress(String address) {
System.out.println("Verifying address using YAHOO AddressVerificationService");
return yahooAVSAPI.validate(address); } }
class GoogleAVS implements AddressVerificationServiceProvider
{ @Override public String validateAddress(String address) {
System.out.println("Verifying address using Google AddressVerificationService");
return googleAVSAPI.validate(address); }
} Now the Client can choose which Service Provider's service to use as follows:
AddressVerificationService verificationService = null;
AddressVerificationServiceProvider provider = null; provider = new YahooAVS();//to use YAHOO AVS provider = new GoogleAVS();//to use Google AVS
verificationService = new AddressVerificationService(provider); String lnl = verificationService.validateAddress("HitechCity, Hyderabad");
System.out.println(lnl); For Unit Testing we can implement a Mock AddressVerificationServiceProvider.
class MockAVS implements AddressVerificationServiceProvider
{ @Override public String validateAddress(String address) {
System.out.println("Verifying address using MOCK AddressVerificationService");
return "<response><longitude>123</longitude><latitude>4567</latitude>"; } }
AddressVerificationServiceProvider provider = null;
provider = new MockAVS();//to use MOCK AVS
AddressVerificationServiceIOC verificationService = new AddressVerificationServiceIOC(provider);
String lnl = verificationService.validateAddress("Somajiguda, Hyderabad"); System.out.println(lnl);
With this approach we elemenated the issues with above Non-IOC/DI based approaches.
o We can provide support for as many Provides as we wish. Just
implement AddressVerificationServiceProvider and inject it. o We can unit test using Dummy Data using Mock Implementation.
Central Authentication Service – CAS: concepts and examples:
The Central Authentication Service (CAS) is a single sign-on protocol for the web.
Its purpose is to permit a user to log into multiple applications simultaneously and
automatically. It also allows untrusted web applications to authenticate users without
gaining access to a user’s security credentials, such as a password. The name CAS
also refers to a software package that implements this protocol.
The Central Authentication Server (CAS) is designed as a standalone web application.
It is currently implemented as several Java servlets and runs through the HTTPS
server on secure.its.yale.edu. It is accessed through three URLs described below:
the login URL, the validation URL, and the optional logout URL.
To use the central authentication service, an application redirects its users, or simply
creates a hyperlink, to the login URL, which for general-purpose Yale users is
https://secure.its.yale.edu/cas/servlet/login. Users may also access this URL
manually if they wish to pre-authenticate their sessions.
The login URL handles actual, “primary” authentication. That is, it prompts the user
for a NetID and a password and validates the pair against Yale’s Kerberos server.
(More specifically, it determines whether or not it can decode a Kerberos IV ticket-
granting ticket for the given NetID with a given password; if it can, it accepts the pair
and throws away the ticket.) To allow for the possibility of automatic re-
authentication later, the CAS also attempts to send an in-memory cookie (one that
expires automatically when the browser closes) back to the browser. This cookie,
which we call a “ticket-granting cookie,” identifies the user as one who has already
logged in successfully.
Why Adopt CAS?
While the most prominent appeal of CAS that is centralizes the user login
implementation and experience, there are many other advantages, including these
listed below.
Participating applications do not touch the end user’s password, and therefore
cannot expose this password if they are compromised
Offers features for proxy authentication
Ability to enforce uniform enterprise authentication and authorization policies
across the system
End to end user audit sessions to improve security reporting and auditing
Removes application developers from having to understand and implement
identity security in their applications
Usually results in significant password help desk cost savings
Government of India has also launched e-Pramaan for e Authentication
http://epramaan.gov.in to adopt CAS.
Chapter-5: Naming Conventions & Coding Pattern
5.1 Introduction
This document describes a set of standards and guidelines for developing programs in the Java language with a consistent style. It is meant to be used not only by programmers directly writing Java code, but also by programmers
creating programs which automatically generate Java code.
The importance and benefits of a consistent coding style are well known. A consistent style:
improves the readability, and therefore, maintainability of code
Facilitates sharing of code among different programmers, especially teams of programmers’ working on the same project.
Allows easier development of automated tools to assist in program development, such as tools which automatically format or pretty-print
source code. Makes it easier to conduct code reviews, another software engineering
process with well-known benefits. In turn, a practice of regular code reviews can help enforce a consistent style.
Saves development time, once the guidelines are learned, by allowing
programmers to focus on the semantics of the code, rather than spend
time trying to determine what particular format is appropriate for a given situation.
However, these standards are not meant to be rigidly enforced without exception. This document does not cover all possible situations. Experience
and informed judgement should be used wherever doubt exists. Consistency of coding style is more important than using a particular style.
These standards are general, not specific to any particular project; project teams may choose to specify a narrower set of additional guidelines for their
project, which includes these guidelines as a subset.
5.1.1 Background
The guidelines presented here were not created in a vacuum. In the process of creating this document, the author has scanned literally hundreds of thousands of lines of existing Java code to determine the
styles being used in current practice. As with most languages, the predominant style is heavily influenced by the style of the original
designers and early developers. As a result, for example, the JDK
(about 600,000 lines of Java source) already largely conforms to this style guide.
The author has also used his extensive experience with C and C++
coding style issues gained from several years of programming as well as from authoring several previous style documents
5.2 Source Files
On file-based host implementations of Java, the compilation unit is a Java source file. A Java source file should contain only one public class or interface definition, although it may it also contain any number of non-public support
classes or interfaces. Source files should be kept to less than 2000 lines. Files longer than this become difficult to manage and maintain. Exceeding this limit
is a good indication that the classes or interfaces should probably be broken up into smaller, more manageable units.
For all but the most trivial projects, source files should be kept under a version management system (such as SCCS or RCS).
5.2.1 Source file naming
Java source file names are of the form:
ClassOrInterfaceName.java
Where ClassOrInterfaceName is exactly the name of the public class or interface defined in the source file and therefore, follows all the naming conventions for classes. The file name suffix is always.java
except on systems that support only three-character extensions; on such systems, the suffix is.jav.
JAR (Java Archive) file names are of the form:
ArchiveName.jar
or ArchiveName.zip
5.2.2 Source file organization
A Java source file should contain the following elements, in the following order:
1. Copyright/ID block comment
2. package declaration
3. import declarations
4. one or more class/interface declarations
At least one blank line should separate all of these element.
5.2.2.1 Copyright/ID block comment
Every source file should start with a block comment containing version information and a standard copy-right notice The version information should be in the following
format:
@(#)module version date [firstname lastname] This can be generated automatically by using the SCCS ID
string:
%W% %E%
Module is the name of the file.version is the source file version used by the version management system. It is not necessarily the same as the class version number. date is the
date of the most recent modification. “ firstnamelastname” is an optional string identifying the creator of the file.
The copyright notice should contain at least the following line:
Copyright (c) yearlist CopyrightHolder. All Rights Reserved.
Where yearlist is a year, a year range, or a comma-separated list of years for which the copyright ap-plies. The
SCCS keyword string %G% can be used in place of specifying the yearlist explicitly. SCCS will fill in the year
automatically upon check out, thereby eliminating the need to update the year list every year. Additional legal text may need to be included depending on the situation. Consult your
legal depart-ment for exact text. Here is the minimal copyright/id block comment for software developed at Sun:
/* * %W% %E%
* Copyright (c) %G% Sun Microsystems, Inc. All Rights Reserved.
*/
5.2.2.2 Package Declaration
Every source file should contain a package declaration. Omitting the package declaration causes the types to be part of an unnamed package, with implementation-defined
semantics. The package statement should start in column 1, and a single space should separate the keyword package
from the package name. Example: Package java.lang;
5.2.2.3 Import Declarations
Import statements should start in column 1, and a single space should separate the keyword import from the type
name. Import statements should be grouped together by package name. A single blank line may be used to separate
groups of import statements. Within groups, import statements should be sorted lexically.
Wildcard type-import-on-demand declarations (e.g. import java.util.*;) should not be used; use fully qualified type
names instead. There are several reasons for this:
• The most important reason is that someone can later add a new unexpected class file to the same package that you are importing. This new class can conflict with a type you
are using from another package, thereby turning a previously correct program into an incorrect one without
touching the program itself. • Explicit class imports clearly convey to a reader the exact
classes that are being used (and which classes are not being used).
• Explicit class imports provide better compile performance.
While type-import-on-demand declarations are convenient
for the programmer and save a little bit of time initially, this time is paid for in increased compile time every time
the file is compiled. The -verbose flag in the javac compiler can be used to
discover which types are actually being imported, in order to convert type-import-on-demand declarations to fully
qualified ones.
5.2.2.4 Class/Interface Declarations
Following the import sections are one or more class declarations and/or interface declarations, collectively
referred to simply as type declarations. The number of type declarations per file should be kept small. There should be at most one public type declaration per file. The public type, if
any, should be the first type declaration in the file.
Every public type declaration should be immediately preceded by a documentation comment describing its function and parameters (using the @param tag). The
description should be concise. Non-public type declarations should also be preceded by a comment, but it need not be a
documentation comment.
5.3 Naming Conventions
The naming conventions specified here apply only to Java code written in the
basic ASCII character set. Terms such as “upper-case” are obviously meaningless for some Unicode character sets.
5.3.1 Package naming
Generally, package names should use only lower-case letters and
digits, and no underscore. Examples:
java.lang
java.awt.image dinosaur.theropod.velociraptor
The unique package prefix scheme suggested should be used for packages that will be publically distributed. In this scheme, a unique
prefix is constructed by using the components of the internet domain name of the host site in reverse order. The first component (top-level
internet domain) is all upper-case, and the remaining components of the prefix are in lower case. Example:
com.acmedonuts.graphics
5.3.2 Class/Interface naming
All type names (classes and interfaces) should use the InfixCaps style. Start with an upper-case letter, and capitalize the first letter of any
subsequent word in the name, as well as any letters that are part of an acronym. All other characters in the name are lower-case. Do not use
underscores to separate words. Class names should be nouns or noun phrases. Interface names depend on the salient purpose of the
interface. If the purpose is primarily to endow an object with a particular capability, then the name should be an adjective (ending in -
able or -ible if possible) that describes the capability; e.g., Searchable, Sortable, NetworkAccessible. Otherwise use nouns or noun phrases.
Examples:
// GOOD type names: LayoutManager, AWTException, ArrayIndexOutOfBoundsException
// BAD type names: ManageLayout // verb phrase
awtException //first letter lower-case array_index_out_of_bounds_exception //underscores
5.3.3 Field naming
Names of non-constant fields (reference types, or non-final primitive
types) should use the infixCaps style. Start with a lower-case letter, and capitalize the first letter of any subsequent word in the name, as well as any letters that are part of an acronym. All other characters in
the name are lower-case. Do not use under-scores to separate words. The names should be nouns or noun phrases. Examples:
Boolean resizable; char recordDelimiter;
Names of fields being used as constants should be all upper-case, with
underscores separating words. The following are considered to be constants:
1. All static final primitive types (Remember that all interface fields are inherently static final).
2. All static final object reference types that are never followed by "." (dot).
3. All static final arrays that are never followed by "[" (dot).
Examples: MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME
One-character field names should be avoided except for temporary and
looping variables. In these cases, use:
• b for a byte
• c for a char
• d for a double • e for an Exception object
• f for a float
• g for a Graphics object
• i, j, k, m, n for integers
• p, q, r, s for String, StringBuffer, or char[] objects An exception is where a strong convention for the one-character name
exists, such as x and y for screen coordinates.
Avoid variable l (“el”) because it is hard to distinguish it from 1 (“one”) on some printers and displays.
5.3.4 Method naming
Method names should use the infixCaps style. Start with a lower-case letter, and capitalize the first letter of any subsequent word in the
name, as well as any letters that are part of an acronym. All other characters in the name are lower-case. Do not use underscores to separate words. Note that this is identical to the naming convention for
non-constant fields; however, it should always be easy to distinguish the two from con-text. Method names should be imperative verbs or
verb phrases. Examples: // GOOD method names:
showStatus(), drawCircle(), addLayoutComponent()
// BAD method names: mouseButton() // noun phrase; doesn’t describe function
DrawCircle() // starts with upper-case letter add_layout_component() // underscores
// The function of this method is unclear. Does it start the // server running (better: startServer()), or test whether or not
// it is running (better: isServerRunning())? serverRunning() // verb phrase, but not imperative
A method to get or set some property of the class should be called getProperty() or setProperty() respectively, where Property is the name
of the property. Examples:
getHeight(), setHeight() A method to test some boolean property of the class should be called
isProperty(), where Property is the name of the property. Examples: isResizable(), isVisible()
5.3.5 Local variable naming
Local variable follow the same naming rules as field names.
5.3.6 Statement label naming Statement labels can be targets of break or continue statements. They
should be all lower-case, with words separated by underscores. Even though the language allows it, do not use the same statement label
name more than once in the same method. Example:
for (int i = 0; i < n; i++) { search: {
for (int j = 0; j < n/2; j++) { if (node[j].name == name) break
search; }
for (int j = n/2; j < n; j++) { if (node[j].name == name) break search;
} } // search }
5.4 White Space Usage
5.4.1 Blank lines
Blank lines can improve readability by grouping sections of the code that are logically related. A blank line should also be used in the
following places:
1. After the copyright block comment, package declaration, and
import section.
2. Between class declarations.
3. Between method declarations.
4. Between the last field declaration and the first method declaration in a class.
5. Before a block or single-line comment, unless it is the first line in
a block.
5.4.2 Blank spaces
A single blank space (not tab) should be used:
1. Between a keyword and its opening parenthesis. This applies to the following keywords: catch, for, if, switch, synchronized,
while. It does not apply to the keywords super and this; these should never be followed by white space.
2. After any keyword that takes an argument. Example: return true;
3. Between two adjacent keywords.
4. Between a keyword or closing parenthesis, and an opening brace
“{”.
5. Before and after binary operators except .(dot). Note that
instance of is a binary operator:
if
(
obj
instanceof Button) {
//
Ri
ght
if
(
obj
instanceof(Button)) {
//
Wr
ong
6. After a comma in a list.
7. After the semi-colons in a for statement, e.g.: for (expr1;
expr2; expr3) {
Blanks should not be used:
1. Between a method name and its opening parenthesis.
2. Some judgement is called for in the case of complex expressions, which may be clearer if the “inner” operators are not surrounded by
spaces and the “outer” ones are. 3. Before or after a .(dot) operator.
4. Between a unary operator and its operand.
5. Between a cast and the expression being casted.
6. After an opening parenthesis or before a closing parenthesis.
7. After an opening square bracket [ or before a closing square bracket ]. Examples:
a += c[i + j] + (int)d + foo(bar(i + j), e); a = (a + b) / (c * d);
if (((x + y) > (z + w)) || (a != (b + 3))) { return foo.distance(x, y); }
Do not use special characters like form-feeds or backspaces.
5.4.3 Indentation
Line indentation is always 4 spaces, for all indentation levels.
The construction of the indentation may include tabs as well as spaces
in order to reduce the file size; how-ever, you may not change the hard tab settings to accomplish this. Hard tabs must be set every 8 spaces
Note: If this rule was not followed, tabs could not be used because they would lack a well-defined meaning.
5.4.4 Continuation lines
Lines should be limited to 80 columns (but not necessarily 80 bytes, for non-ASCII encodings). Lines long-er than 80 columns should be broken
into one or more continuation lines, as needed. All the continuation lines should be aligned, and indented from the first line of the
statement. The amount of the indentation depends on the type of statement.
If the statement must be broken in the middle of a parenthesized expression, such as for compound statements, or for the parameter list
in a method invocation or declaration, the next line should be aligned with the first character to the right of the first unmatched left
parenthesis in the previous line. In all other cases, the continuation lines should be indented by a full standard indentation (4 spaces). If
the next statement after a continuation line is indented by the same amount as the continuation line, then a single blank line should
immediately follow the opening brace to avoid confusing it with the continuation line. It is accept-able to break a long line sooner than absolutely necessary, especially if it improves readability.
Examples:
// RIGHT
foo(long_expression1, long_expression2, long_expression3, long_expression4);
// RIGHT foo(long_expression1,
long_expression2, long_expression3, long_expression4);
// RIGHT - blank line follows continuation line because same indent if (long_logical_test_1 || long_logical_test_2 ||
long_logical_test_3) { statements;
}
A continuation line should never start with a binary operator. Never break a line where normally no white space appears, such as between a method name and its opening parenthesis, or between an array
name and its opening square bracket. Never break a line just before an opening brace “{”
Examples:
// WRONG
while (long_expression1 || long_expression2 || long_expression3) { }
// RIGHT
while (long_expression1 || long_expression2 || long_expression3) { }
5.5 Comments
Java supports three kinds of comments: documentation, block, and single-line comments. These are de-scribed separately in the subsequent sections below.
Here are some general guidelines for comment usage:
• Comments should help a reader understand the purpose of the code. They should guide the reader through the flow of the program, focusing especially on areas which might be confusing or obscure.
• Avoid comments that are obvious from the code, as in this famously bad
comment example:
i = i + 1; // Add one to i
• Remember that misleading comments are worse than no comments at all.
• Avoid putting any information into comments that is likely to become out-
of-date.
• Avoid enclosing comments in boxes drawn with asterisks or other fancy
typography.
• Temporary comments that are expected to be changed or removed later should be marked with the spe-cial tag “ XXX:” so that they can easily be found afterwards. Ideally, all temporary comments should have been
removed by the time a program is ready to be shipped. Example:
// XXX: Change this to call sort() when the bugs in it are fixed list->mySort();
5.5.1 Documentation comments
Java has support for special comments documenting types (classes and interfaces), fields (variables), constructors, and methods,
hereafter referred to collectively as declared entities. The javadoc program can then be used to automatically extract these comments
and generate formatted HTML pages.
A documentation comment should immediately precede the declared
entity, with no blank lines in between. The first line of the comment should be simply the characters /** with no other text on the line,
and should be aligned with the following declared entity. Subsequent lines consist of an asterisk, followed by a single space, followed by comment text, and aligned with the first asterisk of the first line. The
first sentence of the comment text is special, and should be a self-contained summary sentence up to the first period that is followed by
a space, tab, or new-line. Subsequent sentences further describe the declared entity.
The comment text can include embedded HTML tags for better
formatting, with the exceptions of the following tags: <H1>, <H2>, <H3>, <H4>, <H5>, <H6>, <HR>.
Following the comment text are the documentation tag lines. A documentation comment should include all the tags that are
appropriate for the declared entity.
Class and interface comments can use the @version, @author, and @see tags, in that order. If there are multiple authors, use a separate @author tag for each one. Required tags: none.
Constructor comments can use the @param, @exception, and @see
tags, in that order. Required tags: one @param tag for each parameter, and one @exception tag for each exception thrown.
Method comments can use the @param, @return, @exception, and @see tags, in that order. Required tags: one @param tag for each
parameter, one @return tag if the return type is not void, and one @exception tag for each exception thrown.
Variable comments can use only the @see tag. Required tags: none.
All of the above can also use the @deprecated tag to indicate the item might be removed in a future release, and to discourage its continued
use. A documentation comment ends with the characters */. It is also
acceptable to end the comment with the characters **/ to aid in visual identification of the documentation comment.
This is an example of a documentation comment for a method:
/** * Checks a object for “coolness”. Performs a comprehensive
* coolness analysis on the object. An object is cool if it * inherited coolness from its parent; however, an object can * also establish coolness in its own right.
* * @paramobj the object to check for coolness
* @param name the name of the object * @return true if the object is cool; false otherwise. * @exception OutOfMemoryError If there is not enough memory to
* determine coolness. * @exception SecurityException If the security manager cannot be
* created * @see isUncool
* @see isHip **/
publicbooleanisCool(Object obj, String name) throws
OutOfMemoryError, SecurityException { 5.5.2 Block comments
A regular block comment is a traditional “C-style” comment. It starts
with the characters /* and ends with the characters */.
A block comment is always used for the copyright/ID comment at the
beginning of each source file. It is also used to “comment out” several lines of code. Since block comments do not nest, their use in other
parts of the source code would make it difficult to comment out code. Hence, the use of block comments other than for the copyright/ID comment and commenting out code is strongly
discouraged.
5.5.3 Single-line comments
A single-line comment consists of the characters // followed by comment text. There is always a single space between the // and the comment text. A single line comment must be at the same
indentation level as the code that follows it. More than one single-line comment can be grouped together to make a larger comment. A
single-line comment or comment group should always be preceded by a blank line, unless it is the first line in a block. If the comment applies to a group of several following statements, then the comment
or comment group should also be followed by a blank line. If it applies only to the next statement (which may be a compound statement),
then do not follow it with a blank line. Example:
// Traverse the linked list, searching for a match
for (Node node = head; node.next != null; node = node.next) {
Single-line comments can also be used as trailing comments. Trailing comments are similar to single-line comments except they appear on the same line as the code they describe. At least one space should
separate that last non-white space character in the statement, and the trailing comment. If more than one trailing comment appears in a
block of code, they should all be aligned to the same column. Example:
if (!isVisible()) return;
nothing to do
length++; reserve space
for null terminator
Avoid the assembly language style of commenting every line of executable code with a trailing comment.
5.6 Classes
A class declaration looks like the following. Elements in square brackets [] are
optional. [ClassModifiers] class ClassName [Inheritances] { ClassBody
}
ClassModifiersare any combination of the following keywords, in this order: public abstract final
Inheritances are any combination of the following phrases, in this order:
extendsSuperClass
implementsInterfaces
SuperClass is the name of a superclass.Interfaces is the name of an interface, or a comma-separated listof interfaces. If more than one interface is given,
then they should be sorted in lexical order. A class declaration always starts in column 1. All of the above elements of the
class declaration up to and including the opening brace “ {” should appear on a single line (unless it is necessary to break it up into continuation lines if it
exceeds the allowable line length). The ClassBody is indented by the standard indentation of four spaces. The closing brace “ }” appears on its own line in column 1. There should not be a semi-colon following the closing brace. If the
class declaration has one or more continuation lines, then a single blank line should immediately follow the opening brace.
Example:
// Long class declaration that requires 2 continuation lines.
// Notice the opening brace is immediately followed by a blank line. public abstract class VeryLongNameOfTheClassBeingDefined
extendsVeryLongNameOfTheSuperClassBeingExtended implements Interface1, Interface2, Interface3, Interface4 {
static private String buf[256];
}
5.6.1 Class body organization
The body of a class declaration should be organized in the following order1:
1. Static variable field declarations Data 2. Instance variable field declarations
3. Static initializer Code 4. Static member inner class declarations 5. Static method declarations
6. Instance initializer 7. Instance constructor declarations
8. Instance member inner class declarations 9. Instance method declarations
These three elements, fields, constructors, and methods, are collectively referred to as “members”. Within each numbered group
above, sort in lexical order.
5.6.1.1 Member access levels Note that there are four access levels for class members in
Java: public, protected, default, and private, in order of decreasing accessibility. In general, a member should be
given the lowest access level which is appropriate for the member. For example, a member which is only accessed by classes in the same package should be set to default
access. Also, declaring a lower access level will often give the compiler increased opportunities for optimization. On
the other hand, use of private makes it difficult to extend the class by sub classing. If there is reason to believe the class might be sub classed in the future, then members that
might be needed by sub classes should be declared protected instead of private.
5.6.1.2 Member documentation comments
All public members must be preceded by a documentation comment. Protected and default access members may have
a documentation comment as well, at the programmer’s discretion. Private fields should not have a documentation comment. However, all fields that do not have
documentation comments should have single-line comments describing them, if their function is not obvious
from the name.
5.6.1.3 Class and instance variable field declarations
Class variable field declarations, if any, come first. Class variables are those fields which have the keyword static in
their declarations. Instance variable field declarations, if any, come next. Instance variables are those which do not have the keyword static in their declarations. A field
declaration looks like the following. Elements in squarebrackets “ []” are optional.
1. It is tempting to want to group these declarations
together by access level; i.e., group all the public
members together, then the entire default access member, then all the protected members, etc.
However, static/non-static is a more important conceptual distinction than access level. Also, there are so many different access levels in Java that it
becomes too con-fusing, and does not work well in practice.
2. The private protected access level is obsolete and
should not be used. [FieldModifiers] Type FieldName [= Initializer];
FieldModifiersare any legal combination of the following
keywords, in this order: public protected private static final transient volatile
Always put field declarations on separate line; do not group
them together on a single line:
static private int useCount, index;
//Wrong
static private int useCount;//Right
static private long index; //Right
A field which is never changed after initialization should be declared
final. This not only serves as useful documentation to the reader, but also allows the compiler to generate more efficient code. It is also a
good idea to align the field names so that they all start in the same column.
5.6.1.4 Static initializer
A static initializer, if any, comes next. It is called when the class is first referenced, before any constructors are called.
It is useful for initializing blank static final fields (static final fields not initialized at point of declaration). There should at
most one static initializer per class. It has the following form:
static { statements; }
5.6.1.5 Static member inner class declarations
Static inner (nested) classes which pertain to a class as a whole rather than any particular instance, if any, come
next:
public class Outer { static class Inner { // static inner class }
}
5.6.1.6 Static method declarations
Any static methods come next. A static method follows the same rules as instance methods. Note that main() is a static method.
5.6.1.7 Instance initializer
An instance (non-static) initializer, if any, comes next. If present, it is called from every constructor after any calls to
super-class constructors. It is useful for initializing blank final fields (final fields not initialized at point of declaration),
and for initializing anonymous inner classes since they cannot declare constructors. There should be at most one instance initializer per class:
// Instance initializer
{ statements; }
5.6.1.8 Constructor declarations
Constructor declarations, if any, come next. All of the elements of the constructor declaration up to and including
the opening brace “ {” should appear on a single line (unless it is necessary to break it up into continuation lines
if it exceeds the allowable line length). Example
/**
* Constructs a new empty FooBar. */
publicFooBar() { value = new char[0]; }
If there is more than one constructor, sort them lexically by
formal parameter list, with constructors having more parameters always coming after those with fewer parameters. This implies that a constructor with no
arguments (if it exists) is always the first one.
5.6.1.9 Instance method declarations
Instance method declarations, if any, come next. Instance methods
are those which do not have the keyword static in their declarations.
5.6.2 Method declarations
All of the elements of a method declaration up to and including the opening brace “ {” should appear on a single line (unless it is necessary to break it up into continuation lines if it exceeds the
allowable line length). A method declaration looks like the following.
Elements in square brackets “ {” are optional.
[MethodModifiers] Type MethodName(Parameters) [throws Exceptions] {
MethodModifiersare any combination of the following phrases, in this order:
public protected private abstract static final synchronized native
Exceptions is the name of an exception, or a comma-separated list of exceptions. If more than one excep-tion is given, then they should be
sorted in lexical order.
Parameters is the list of formal parameter declarations. Parameters may be declaredfinalin order tomake the compiler enforce that the parameter is not changed in the body of the method, as well as to
provide useful documentation to the reader. Parameters must be declared final in order to make them available to local inner classes.
A method that will never be overridden by a sub-class should be declared final. This allows the compiler to generate more efficient
code. Methods that are private, or declared in a class that is final, are im-plicitly final; however, in these cases the method should still be
explicitly declared final for clarity. Methods are sorted in lexical order, with one exception: if there is a
finalize() method, it should be the very last method declaration in the class. This makes it easy to quickly see whether a class has a fi-
nalize() method or not. If possible, a finalize() method should call super.finalize() as the last action it performs. If the method declaration has one or more continuation lines, then a single blank
line should immediately follow the opening brace.
Examples: // Long method declaration that requires a continuation line.
// Note the opening brace is immediately followed by a blank line.
public static final synchronized long methodName() throwsArithmeticException, InterruptedException {
staticint count; }
// Line broken in the middle of a parameter list
// Align just after left parenthesis publicbooleanimageUpdate(Image img, intinfoflags, int x, int y, int w,
int h) { int i;
} 5.6.3 Local inner classes
Inner (nested) classes may be declared local to a method. This makes
the inner class unavailable to any oth-er method in the enclosing class. They follow the same format rules as top-level classes:
Enumeration enumerate() { classEnum implements Enumeration {
} return new Enum();
}
5.6.4 Anonymous inner classes
Anonymous classes can be used when then following conditions are met:
1. The class is referred to directly in only one place.
2. The class definition is simple, and contains only a few lines. In all
other cases, use named classes (inner or not) instead.
AWT Listeners are a common case where anonymous classes are
appropriate. In many such cases, the only purpose of the class is simply to call another method to do most of
the work of handling an event.
Anonymous inner classes follow similar rules as named classes; however there are a few rules specific to anonymous classes:
• When possible, the wholenew expression, consisting of the new operator, the type name, and opening brace, should appear on
the same line as the expression of which it is a part. If it does not fit on the line, then the whole new expression should moved to
the next line as a unit. • The body of the anonymous class should be indented by the
normal indentation from the beginning of the line that contains the new expression.
• The closing brace should not be on a line by itself, but should be
followed whatever tokens are required by the rest of the
expression. Usually, this means the closing brace is followed by at least a semi-colon, closing parenthesis, or comma. The closing
brace is indented to the same level as the line containing the new expression. There is no space immediately following the closing brace.
Examples:
// Anonymous class inside a return expression Enumeration
myEnumerate(final Object array[]) {
return new Enumeration() { // new on same line int count = 0;
publicbooleanhasMoreElements() { return count <array.length; }
public Object nextElement() { return array[count++];
} }; // } followed by ;
}
// Anonymous class inside a parenthesized expression helpButton.addActionListener(new ActionListener() { public void
actionPerformed(ActionEvent e) { showHelp(); }
}); // } followed by );
5.6.5 Anonymous array expressions and array initializers
Anonymous arrays can be used wherever an array value is needed. If
the entire anonymous array expres-sion fits on one line, then it is acceptable to place it on a single line. Otherwise, there should be one
initial-izer per line, with the same rules as for anonymous inner classes. The same rules also apply to array initializers in array declarations.
// Example where entire array expression fits on one line
Polygon p = new Polygon(new int[] {0, 1, 2},
newint[] {10, 11, 12}, 3); // Example with one array initializer per line String
errorMessages[] = {
"No such file or directory", "Unable to open file", "Unmatched parentheses in expression" };
// Example of embedded anonymous array expression
createMenuItems(new menuItemLabels[] { "Open",
"Save", "Save As...", "Quit",
}); 5.7 Interfaces
Interfaces follows a similar style to classes. An interface declaration looks like the following. Elements in square brackets “ []” are optional.
[public] interface InterfaceName [extends SuperInterfaces] { InterfaceBody }
SuperInterfacesis the name of an interface, or a comma-separated list of
interfaces. If more than one in-terface is given, then they should be sorted in lexical order.
An interface declaration always starts in column 1. All of the above elements of the interface declaration up to and include the opening brace “ {” should
appear on a single line (unless it is necessary to break it up into continuation lines if it exceeds the allowable line length). The InterfaceBody is indented by the stan-dard indentation of four spaces. The closing brace “ }” appears on its
own line in column 1.There should not be a semi-colon following the closing brace.
All interfaces are inherently abstract; do not explicitly include this keyword in the declaration of an interface.
All interface fields are inherently public, static, and final; do not explicitly
include these keywords in the declaration of an interface field. All interface methods are inherently public and abstract; do not explicitly
include these keywords in the declaration of an interface method.
Except as otherwise noted, interface declarations follow the same style guidelines as classes.
5.7.1 Interface body organization
The body of an interface declaration should be organized in the following order:
1. Interface constant field declarations.
2. Interface method declarations
The declaration styles of interface fields and methods are identical to the styles for class fields and methods.
5.8 Statements
5.8.1 Simple statements
5.8.2 Assignment and expression statements
Each line should contain at most one statement. For example,
A = b + c; count++; // wrong
A = b + c; //
r
ig
ht
count++; //
ri
gh
t 5.8.3 Local variable declarations
Generally local variable declarations should be on separate lines;
however, an exception is allowable for temporary variables that do not require initializers. For example,
i
nt i, j = 4, k; // WRONG
in
t
i
, k; //
accep
table i
nt j = 4; //
RIGHT
Local variables may be declared final in order to make the compiler enforce that the variable is not changed after initialization, as well as
to provide useful documentation to the reader. Local variables must be declared final in order to make them available to local inner classes.
5.8.4 Array declarations
The brackets “ []” in array declarations should immediately follow the array name, not the type. The ex-ception is for method return values,
where there is no separate name; in this case the brackets immediately follow the type:
char[] buf; // WRONG char buf[]; // RIGHT
String[] getNames() { // RIGHT, method return value
5.8.5 if statement
if (condition) { statements; }
if (condition) { statements;
} else { statements;
} if (condition) { statements;
} else if (condition) { statements;
} else { statements; }
5.8.6 for statement
for (initialization; condition; update) { statements; }
5.8.7 while statement
while (condition) { statements;
} For “infinite” loops, use the following rather than “ for (;;) { ... }” :
while (true) { statements;
} 5.8.8 do-while statement
do {
statements; } while (condition);
5.8.9 switch statement
switch (condition) { case 1: case 2: statements;break;
case 3: statements;break;
default: statements;break; }
5.8.10 try statement
try { statements;
} catch (exception-declaration) { statements;
}
try { statements; } finally { statements;
}
try { statements; } catch (exception-declaration) { statements;
} finally { statements;
}
5.8.11 synchronized statement
synchronized (expression) { statements;
} 5.8.12 Labelled statements
Labeled statements should always be enclosed in braces “ {}”. The label itself should be indented to the normal indentation level,
followed by a colon, single space, and opening brace. The closing brace should have a trailing comment on the same line with the label
repeated: statement-label: {} // statement-label
Java Coding Style Example
/* @(#)CodingStyleExample.java 19/Oct/2015 Abhinav Kumar
* Copyright (c) 1994-1998 Sun Microsystems, Inc. All Rights Reserved. *
*/ packagecom.sun.examples;
import java.applet.Applet; import java.awt.Point; /**
* A class to demonstrate good coding style. */ public class CodingStyleExample extends Applet implements Runnable {
static final int BUFFER_SIZE = 4096;
// default buffer
StringBuffer name;
// my name
Point starshipCoordinates[]; //
ship locations
/** * Compute the total distance between a set of Points. * @paramstarshipCoordinates the locations of all known starships
* @paramnumberOfPoints the number of points in the array * @return the total distance
*/ publicintcomputeDistances(Point starshipCoordinates[], intnumberOfPoints) throws Exception {
int distance = 0; // accumulates distances
// Compute distance to each starship and add it to the total for (int i = 0; i <numberOfPoints; i++) {
distance += Math.sqrt((double)((starshipCoordinates[i].x * starshipCoordinates[i].x) + (starshipCoordinates[i].y * starshipCoordinates[i].y)));
}
if (distance > 100000) { throw new Exception(); } return distance;
} /**
* Called whenever Thread.start() is called for this class */ public void run() { try { name.append("X");
System.out.println(name); } catch (Exception e) {
name = new StringBuffer(BUFFER_SIZE); } }
}
Report prepared under the guidance of:
Sri G.P.Singh
Senior Technical Director and ASIO
Uttar Pradesh State Unit,
Lucknow.
Report Compiled by:
Sri Sanjay Chatterjee
Principal Systems Analyst
Uttar Pradesh State Unit,
Lucknow.
Useful Contribution from:
Sri Shailendra Johri
Principal Systems Analyst
Uttar Pradesh State Unit,
Lucknow.
Logistics and Support from:
Sri Varun Nangia
Technical Director
Uttar Pradesh State Unit,
Lucknow.
Sri Sunil Sharma
Technical Director
Uttar Pradesh State Unit,
Lucknow.