Featured FREE Whitepapers

What's New Here?

jboss-resteasy-logo

RESTEasy Tutorial Part-2: Spring Integration

RESTEasy provides support for Spring integration which enables us to expose Spring beans as RESTful WebServices.                     Step#1: Configure RESTEasy+Spring dependencies using Maven. <project xmlns='http:maven.apache.orgPOM4.0.0' xmlns:xsi='http:www.w3.org2001XMLSchema-instance' xsi:schemaLocation='http:maven.apache.orgPOM4.0.0 http:maven.apache.orgmaven-v4_0_0.xsd'> <modelVersion>4.0.0<modelVersion> <groupId>com.sivalabs<groupId> <artifactId>resteasy-demo<artifactId> <version>0.1<version> <packaging>war<packaging> <properties> <project.build.sourceEncoding>UTF-8<project.build.sourceEncoding> <org.springframework.version>3.1.0.RELEASE<org.springframework.version> <slf4j.version>1.6.1<slf4j.version> <java.version>1.6<java.version> <junit.version>4.8.2<junit.version> <resteasy.version>2.3.2.Final<resteasy.version> <properties> <build> <finalName>resteasy-demo<finalName> <build> <dependencies> <dependency> <groupId>junit<groupId> <artifactId>junit<artifactId> <scope>test<scope> <dependency> <dependency> <groupId>org.slf4j<groupId> <artifactId>slf4j-api<artifactId> <version>${slf4j.version}<version> <dependency> <dependency> <groupId>org.slf4j<groupId> <artifactId>jcl-over-slf4j<artifactId> <version>${slf4j.version}<version> <scope>runtime<scope> <dependency> <dependency> <groupId>org.slf4j<groupId> <artifactId>slf4j-log4j12<artifactId> <version>${slf4j.version}<version> <scope>runtime<scope> <dependency> <dependency> <groupId>log4j<groupId> <artifactId>log4j<artifactId> <version>1.2.16<version> <scope>runtime<scope> <dependency> <dependency> <groupId>org.springframework<groupId> <artifactId>spring-context-support<artifactId> <version>${org.springframework.version}<version> <exclusions> <exclusion> <artifactId>commons-logging<artifactId> <groupId>commons-logging<groupId> <exclusion> <exclusions> <dependency> <dependency> <groupId>org.springframework<groupId> <artifactId>spring-web<artifactId> <version>${org.springframework.version}<version> <dependency> <dependency> <groupId>org.jboss.resteasy<groupId> <artifactId>resteasy-jaxrs<artifactId> <version>${resteasy.version}<version> <scope>provided<scope> <dependency> <dependency> <groupId>org.jboss.resteasy<groupId> <artifactId>resteasy-jaxb-provider<artifactId> <version>${resteasy.version}<version> <scope>provided<scope> <dependency> <dependency> <groupId>org.jboss.resteasy<groupId> <artifactId>jaxrs-api<artifactId> <version>2.3.0.GA<version> <scope>provided<scope> <dependency> <dependency> <groupId>org.jboss.resteasy<groupId> <artifactId>resteasy-spring<artifactId> <version>2.3.0.GA<version> <exclusions> <exclusion> <artifactId>commons-logging<artifactId> <groupId>commons-logging<groupId> <exclusion> <exclusion> <artifactId>org.jboss.resteasy<artifactId> <groupId>resteasy-jaxb-provider<groupId> <exclusion> <exclusion> <artifactId>jaxb-impl<artifactId> <groupId>com.sun.xml.bind<groupId> <exclusion> <exclusion> <artifactId>sjsxp<artifactId> <groupId>com.sun.xml.stream<groupId> <exclusion> <exclusion> <artifactId>jsr250-api<artifactId> <groupId>javax.annotation<groupId> <exclusion> <exclusion> <artifactId>resteasy-jaxb-provider<artifactId> <groupId>org.jboss.resteasy<groupId> <exclusion> <exclusion> <artifactId>activation<artifactId> <groupId>javax.activation<groupId> <exclusion> <exclusions> <dependency> <dependency> <groupId>javax.servlet<groupId> <artifactId>servlet-api<artifactId> <version>2.5<version> <scope>provided<scope> <dependency> <dependency> <groupId>org.apache.httpcomponents<groupId> <artifactId>httpclient<artifactId> <version>4.1.2<version> <dependency> <dependencies> <project> Step#2: Configure RESTEasy+Spring in web.xml <web-app xmlns:xsi='http:www.w3.org2001XMLSchema-instance' xmlns='http:java.sun.comxmlnsjavaee' xmlns:web='http:java.sun.comxmlnsjavaeeweb-app_2_5.xsd' xsi:schemaLocation='http:java.sun.comxmlnsjavaee http:java.sun.comxmlnsjavaeeweb-app_3_0.xsd' id='WebApp_ID' version='3.0'> <listener> <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap<listener-class> <listener> <listener> <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener<listener-class> <listener> <servlet> <servlet-name>Resteasy<servlet-name> <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher<servlet-class> <servlet> <servlet-mapping> <servlet-name>Resteasy<servlet-name> <url-pattern>rest*<url-pattern> <servlet-mapping> <context-param> <param-name>contextConfigLocation<param-name> <param-value>classpath:applicationContext.xml<param-value> <context-param> <context-param> <param-name>resteasy.servlet.mapping.prefix<param-name> <param-value>rest<param-value> <context-param> <context-param> <param-name>resteasy.scan<param-name> <param-value>true<param-value> <context-param> <web-app> Step#3: Create a Spring Service class UserService and update UserResource to use UserService bean. package com.sivalabs.resteasydemo; import java.util.List; import org.springframework.stereotype.Service; import com.sivalabs.resteasydemo.MockUserTable; @Service public class UserService { public void save(User user){ MockUserTable.save(user); } public User getById(Integer id){ return MockUserTable.getById(id); } public List<User> getAll(){ return MockUserTable.getAll(); } public void delete(Integer id){ MockUserTable.delete(id); } } package com.sivalabs.resteasydemo; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.GenericEntity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component @Path('users') @Produces(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATION_XML) public class UserResource { @Autowired private UserService userService; @Path('') @GET public Response getUsersXML() { List<User> users = userService.getAll(); GenericEntity<List<User>> ge = new GenericEntity<List<User>>(users){}; return Response.ok(ge).build(); } @Path('{id}') @GET public Response getUserXMLById(@PathParam('id') Integer id) { User user = userService.getById(id); return Response.ok(user).build(); } @Path('') @POST public Response saveUser(User user) { userService.save(user); return Response.ok('<status>success<status>').build(); } @Path('{id}') @DELETE public Response deleteUser(@PathParam('id') Integer id) { userService.delete(id); return Response.ok('<status>success<status>').build(); } } package com.sivalabs.resteasydemo; import java.util.List; import org.springframework.stereotype.Service; import com.sivalabs.resteasydemo.MockUserTable; @Service public class UserService { public void save(User user){ MockUserTable.save(user); } public User getById(Integer id){ return MockUserTable.getById(id); } public List<User> getAll(){ return MockUserTable.getAll(); } public void delete(Integer id){ MockUserTable.delete(id); } } package com.sivalabs.resteasydemo; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.GenericEntity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component @Path('users') @Produces(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATION_XML) public class UserResource { @Autowired private UserService userService; @Path('') @GET public Response getUsersXML() { List<User> users = userService.getAll(); GenericEntity<List<User>> ge = new GenericEntity<List<User>>(users){}; return Response.ok(ge).build(); } @Path('{id}') @GET public Response getUserXMLById(@PathParam('id') Integer id) { User user = userService.getById(id); return Response.ok(user).build(); } @Path('') @POST public Response saveUser(User user) { userService.save(user); return Response.ok('<status>success<status>').build(); } @Path('{id}') @DELETE public Response deleteUser(@PathParam('id') Integer id) { userService.delete(id); return Response.ok('<status>success<status>').build(); } } applicationContext.xml <?xml version='1.0' encoding='UTF-8'?> <beans xmlns='http:www.springframework.orgschemabeans' xmlns:xsi='http:www.w3.org2001XMLSchema-instance' xmlns:p='http:www.springframework.orgschemap' xmlns:context='http:www.springframework.orgschemacontext' xsi:schemaLocation='http:www.springframework.orgschemabeans http:www.springframework.orgschemabeansspring-beans.xsd http:www.springframework.orgschemacontext http:www.springframework.orgschemacontextspring-context.xsd'> <context:annotation-config> <context:component-scan base-package='com.sivalabs.resteasydemo'> <beans> Step#4: Same JUnit TestCase to test the REST Webservice described in Part-1. package com.sivalabs.resteasydemo; import java.util.List; import org.jboss.resteasy.client.ClientRequest; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.util.GenericType; import org.junit.Assert; import org.junit.Test; import com.sivalabs.resteasydemo.User; public class UserResourceTest { static final String ROOT_URL = 'http:localhost:8080resteasy-demorest'; @Test public void testGetUsers() throws Exception { ClientRequest request = new ClientRequest(ROOT_URL+'users'); ClientResponse<List<User>> response = request.get(new GenericType<List<User>>(){}); List<User> users = response.getEntity(); Assert.assertNotNull(users); } @Test public void testGetUserById() throws Exception { ClientRequest request = new ClientRequest(ROOT_URL+'users1'); ClientResponse<User> response = request.get(User.class); User user = response.getEntity(); Assert.assertNotNull(user); } @Test public void testSaveUser() throws Exception { User user = new User(); user.setId(3); user.setName('User3'); user.setEmail('user3@gmail.com'); ClientRequest request = new ClientRequest(ROOT_URL+'users'); request.body('applicationxml', user); ClientResponse<String> response = request.post(String.class); String statusXML = response.getEntity(); Assert.assertNotNull(statusXML); } @Test public void testDeleteUser() throws Exception { ClientRequest request = new ClientRequest(ROOT_URL+'users2'); ClientResponse<String> response = request.delete(String.class); String statusXML = response.getEntity(); Assert.assertNotNull(statusXML); } }Important Things to Keep in mind: 1. org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap Listener should be registered before any other listener. 2. You should configure resteasy.servlet.mapping.prefix @lt;context-param> if the HttpServletDispatcher servlet url-pattern is anything other than /* 3. You should register REST Resource as Spring bean by annotating with @Component or @Service. Reference: RESTEasy Tutorial Part-2: Spring Integration from our JCG partner Siva Reddy at the My Experiments on Technology blog....
eclipse-logo

Eclipse Project: Releases, Plans, and Reviews

For each release, an Eclipse project is required to provide a project plan. The project plan is created at the beginning of a release cycle and may be modified throughout the cycle. The plan tells the community what the main areas of focus are in the project. This lets, for example, contributors know what kinds of contributions are going to be valuable so they can direct their attention accordingly. It also lets adopters know what to expect from the project for an upcoming release (which may help them to decide to get involved).At the end of a release cycle, an Eclipse project is required to provide a release review document. For project committers, it serves as a retrospective. It is a chance to look back and reflect on the work done, decide what worked and what didn’t work, and start thinking about the next release cycle. For adopters it is confirmation of the plan and a last chance to update their own plans for how they will incorporate the project code into their own development schedule. For the rest of the community, the review document serves as a description of the changes and a way to learn about what’s new, what’s interesting, and what they should care about.Our current system keeps track of all this information in a variety of different locations. Project plans are represented as XML files and are stored somewhere within the Eclipse infrastructure (the website, a source repository, or the download site). Basic information about the release, including the name and date is specified in release records in the project metadata in the Eclipse Developer Portal. Release records are relatively limited in terms of the information they can contain; they are restricted to just the basic information, along with links to the project plan, and new and noteworthy documents.Release review documentation is currently provided in a variety of different formats (e.g. HTML, PDF, PPT, ODP). When a project wants to do a release, they need to tell me. I create a record in the Developer Portal and point that record to the review document that we now store in a corresponding Bugzilla record. Unfortunately, the current system makes no explicit connect connection between the release and the corresponding review document (I’ve added some code that uses some heuristics to figure it out).Sounds awful. Right?The new system that Nathan and I are working on brings all these elements together. A project can specify any number of releases, projecting as far as they’d like into the future. The project plan, rather than being in a separately-managed document, is part of the release record. It can be specified at the beginning of a release cycle and updated throughout. The review information is also attached directly to the release record; it too can be updated throughout the release cycle. I think one of the key benefits is that all of the information is kept together in a very consistent form that can be easily organized and disseminated in different ways. Revision management is built in so it’s easy to tell who made changes, compare and revert changes, and so on.In my opinion, Nathan’s done a great job with the look and feel. Here is what the BIRT project’s 4.2 release looks like:Note the separate tabs for different elements of the release. Note also that this is just display-only: I don’t have the necessary access to edit this project’s releases. I do, however, have access rights to edit information for the Dash project’s releases:When editing, separate tabs provide access to the description, plan, and review items. And, again, there’s revision tracking and management.So the big question: will you use it? Or do we need to provide the ability to attach separate plan and review documents?I’ll be showing this off at EclipseCon 2012 at a BoF. If you can’t attend the BoF, corner me: I’ll be prepared to demo what we have to anybody wants to see it. We’re going to roll out a version of this that you can play with in the weeks following EclipseCon; with a plan to roll it out as a replacement for the Developer Portal and Data-Driven Project Websites post-Juno (i.e. July 2012). Reference: Releases, Plans, and Reviews from our JCG partner Wayne Beaton at the Eclipse Hints, Tips, and Random Musings blog....
java-interview-questions-answers

Java JAAS form based authentication

Implementing a login module using JAAS is an of advance topic and also most of the developers have rare chance of involving with this kind of development. But the basic implementation of JAAS login module is not that much hard implementation.That is because, I intended to post this.Here, I am explaining, how to implement a tomcat managed authentication module. This implementation is not container dependent one. We can use it with any container with slight configuration change.As the first step, We need to create a login module class which implements javax.security.auth.spi.LoginModule interface. This interface exposes 5 methods that must be implemented by our login module class. Those are initialize(), login(), commit(), abort(), logout().initialize() method is passed four arguments .The ‘Subject’ is what, We need to authenticate. The subject can represents the related information for a single login user. It can represent identities like ‘username’, ‘password’ etc. And also, it can represents the roles assigned to the user. All these identities should be represent as java.security.Principal. So We should create separate classes to distinguish these entities by implementing java.security.Principal. In my tutorial, I have created separate classes for username, password and role as JAASUserPrincipal, JAASPasswordPrincipal and JAASRolePrincipal. Subject’s getPrincipals() method returns a set of java.security.Principal associated with the subject. To distinguish these, it is important of Creating separate classes for each identity.The ‘ CallbackHandler‘ is used to communicate with the user. When authenticating the user by the login module, the login module invokes the handle() method of the CallbackHandler instance to get the user name and password. We do not want to worry about CallbackHandler instance yet. Because the container manages to provide the required callbakcs. The tomcat provides JAASCallbackHandler for this purpose. But, If We want to invoke the authentication explicitly, We need to create our own call back handler class by implementing the javax.security.auth.callback.CallbackHandler. I will explain this at the end of the tutorial.The next important argument for initialize() method is ‘options’. These options where We declare those in ‘ jass.config‘ file. With the initialisation of login module, map of options declared in ‘jass.config’ file are provided. I will explain the ‘jaas.config’ file of our tutorial later.Next, I will show the full source code for our principal classes. JAASUserPrincipal.java package com.rainyday.server.login;import java.io.Serializable; import java.security.Principal;/** * @author semika * */ public class JAASUserPrincipal implements Principal, Serializable {private String name; /** * @param name */ public JAASUserPrincipal(String name) { if (name == null) { throw new NullPointerException("NULL user name"); } this.name = name; } @Override public String getName() { return name; }@Override public String toString() { return "UserPrincipal [name=" + name + "]"; }@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; }@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; JAASUserPrincipal other = (JAASUserPrincipal) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }JAASRolePrincipal.java package com.rainyday.server.login;import java.io.Serializable; import java.security.Principal;/** * @author semika * */ public class JAASRolePrincipal implements Principal, Serializable {private String name; /** * @param name */ public JAASRolePrincipal(String name) { if (name == null) { throw new NullPointerException("NULL role name"); } this.name = name; }@Override public String getName() { return name; }@Override public String toString() { return "JASSRolePrincipal [name=" + name + "]"; }@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; }@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; JAASRolePrincipal other = (JAASRolePrincipal) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } } JAASPasswordPrincipal.java package com.rainyday.server.login;import java.io.Serializable; import java.security.Principal;/** * @author semika * */ public class JAASPasswordPrincipal implements Principal, Serializable {private String name; /** * @param name */ public JAASPasswordPrincipal(String name) { if (name == null) { throw new NullPointerException("NULL password."); } this.name = name; }@Override public String getName() { return name; }@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; }@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; JAASPasswordPrincipal other = (JAASPasswordPrincipal) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; }@Override public String toString() { return "JAASPasswordPrincipal [name=" + name + "]"; }}The above three classes are exactly similar. But, We need to create separate classes for each principal to distinguish them.The login() method of login module performs the authentication. This validates the user entered user name and password with the database. Now, You may have a problem, How login details entered by the user comes into the login() method. As I explained earlier, the call back handler brings the login identities into the login() method. From the login() method, the login module invokes the handle() method of call back handler by passing the required call backs into it. Then handle() method populates those call backs with the required information and make available to login() method.The commit() method is invoked by the login module after the successful authentication. The subject can be populated with associated principals. For example, We can retrieve user assigned roles from the database and attached those to the subject.The next, I will explain the required configurations to work this login module.We should create ‘jass.config’ file and should be placed that file under ‘$CATALINA_HOME/conf‘. The ‘jass.config’ file of this tutorial is as follows. rainyDay { com.rainyday.server.login.JAASLoginModule required dbDriver="com.mysql.jdbc.Driver" dbURL="jdbc:mysql://localhost/rainyday" dbUser="root" dbPassword="abc123" userQuery="select username from secu_user where secu_user.username=? and secu_user.password=?" roleQuery="select secu_user_role.rolename from secu_user, secu_user_role " + "where secu_user.username=secu_user_role.username and secu_user.username=?" debug=true; };‘jass.config’ file should have this similar format. In addition to the login module declaration, You can declare options as your wish. These options are made available by login module with ‘options’ map in initialize() method argument. Additionally, We should tell the tomcat, Where to locate the ‘jaas.config’ file by adding it’s path to JAVA_OPTS environment variable. I have added this into ‘catalina.sh’ file under $CATALINA_HOME/bin as follows. JAVA_OPTS=”$JAVA_OPTS -Djava.security.auth.login.config==../conf/jaas.config” Next, You need to declare the JAASRealm configurations. You can add a new ‘Realm’ entry into the server.xml file under $CATALINA_HOME/conf. In our tutorial, the ‘Realm’ entry is as follows.                   <Realm className="org.apache.catalina.realm.JAASRealm" appName="rainyDay" userClassNames="com.rainyday.server.login.JASSUserPrincipal,com.rainyday.server.login.JAASPasswordPrincipal" roleClassNames="com.rainyday.server.login.JASSRolePrincipal"/>For apache tomcat’s realm configuration, You can view this documentation. The complete source code for our jaas login module. JAASLoginModule.java package com.rainyday.server.login;import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map;import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule;import org.apache.log4j.Logger;/** * @author semika * */ public class JAASLoginModule implements LoginModule { private static Logger LOGGER = Logger.getLogger(JAASLoginModule.class); // initial state private Subject subject; private CallbackHandler callbackHandler; private Map sharedState; private Map options;// configurable option private boolean debug = false; // the authentication status private boolean succeeded = false; private boolean commitSucceeded = false; //user credentials private String username = null; private char[] password = null; //user principle private JAASUserPrincipal userPrincipal = null; private JAASPasswordPrincipal passwordPrincipal = null; public JAASLoginModule() { super(); }@Override public void initialize(Subject subject, CallbackHandler callbackHandler, Map<string, ?=""> sharedState, Map<string, ?=""> options) { this.subject = subject; this.callbackHandler = callbackHandler; this.sharedState = sharedState; this.options = options; debug = "true".equalsIgnoreCase((String)options.get("debug")); }@Override public boolean login() throws LoginException { if (callbackHandler == null){ throw new LoginException("Error: no CallbackHandler available " + "to garner authentication information from the user"); } Callback[] callbacks = new Callback[2]; callbacks[0] = new NameCallback("username"); callbacks[1] = new PasswordCallback("password: ", false); try { callbackHandler.handle(callbacks); username = ((NameCallback)callbacks[0]).getName(); password = ((PasswordCallback)callbacks[1]).getPassword(); if (debug) { LOGGER.debug("Username :" + username); LOGGER.debug("Password : " + password); } if (username == null || password == null) { LOGGER.error("Callback handler does not return login data properly"); throw new LoginException("Callback handler does not return login data properly"); } if (isValidUser()) { //validate user. succeeded = true; return true; } } catch (IOException e) { e.printStackTrace(); } catch (UnsupportedCallbackException e) { e.printStackTrace(); } return false; }@Override public boolean commit() throws LoginException { if (succeeded == false) { return false; } else { userPrincipal = new JAASUserPrincipal(username); if (!subject.getPrincipals().contains(userPrincipal)) { subject.getPrincipals().add(userPrincipal); LOGGER.debug("User principal added:" + userPrincipal); } passwordPrincipal = new JAASPasswordPrincipal(new String(password)); if (!subject.getPrincipals().contains(passwordPrincipal)) { subject.getPrincipals().add(passwordPrincipal); LOGGER.debug("Password principal added: " + passwordPrincipal); } //populate subject with roles. List<string> roles = getRoles(); for (String role: roles) { JAASRolePrincipal rolePrincipal = new JAASRolePrincipal(role); if (!subject.getPrincipals().contains(rolePrincipal)) { subject.getPrincipals().add(rolePrincipal); LOGGER.debug("Role principal added: " + rolePrincipal); } } commitSucceeded = true; LOGGER.info("Login subject were successfully populated with principals and roles"); return true; } }@Override public boolean abort() throws LoginException { if (succeeded == false) { return false; } else if (succeeded == true && commitSucceeded == false) { succeeded = false; username = null; if (password != null) { password = null; } userPrincipal = null; } else { logout(); } return true; }@Override public boolean logout() throws LoginException { subject.getPrincipals().remove(userPrincipal); succeeded = false; succeeded = commitSucceeded; username = null; if (password != null) { for (int i = 0; i < password.length; i++){ password[i] = ' '; password = null; } } userPrincipal = null; return true; } private boolean isValidUser() throws LoginException {String sql = (String)options.get("userQuery"); Connection con = null; ResultSet rs = null; PreparedStatement stmt = null; try { con = getConnection(); stmt = con.prepareStatement(sql); stmt.setString(1, username); stmt.setString(2, new String(password)); rs = stmt.executeQuery(); if (rs.next()) { //User exist with the given user name and password. return true; } } catch (Exception e) { LOGGER.error("Error when loading user from the database " + e); e.printStackTrace(); } finally { try { rs.close(); } catch (SQLException e) { LOGGER.error("Error when closing result set." + e); } try { stmt.close(); } catch (SQLException e) { LOGGER.error("Error when closing statement." + e); } try { con.close(); } catch (SQLException e) { LOGGER.error("Error when closing connection." + e); } } return false; }/** * Returns list of roles assigned to authenticated user. * @return */ private List<string> getRoles() { Connection con = null; ResultSet rs = null; PreparedStatement stmt = null; List<string> roleList = new ArrayList<string>(); try { con = getConnection(); String sql = (String)options.get("roleQuery"); stmt = con.prepareStatement(sql); stmt.setString(1, username); rs = stmt.executeQuery(); if (rs.next()) { roleList.add(rs.getString("rolename")); } } catch (Exception e) { LOGGER.error("Error when loading user from the database " + e); e.printStackTrace(); } finally { try { rs.close(); } catch (SQLException e) { LOGGER.error("Error when closing result set." + e); } try { stmt.close(); } catch (SQLException e) { LOGGER.error("Error when closing statement." + e); } try { con.close(); } catch (SQLException e) { LOGGER.error("Error when closing connection." + e); } } return roleList; } /** * Returns JDBC connection * @return * @throws LoginException */ private Connection getConnection() throws LoginException { String dBUser = (String)options.get("dbUser"); String dBPassword = (String)options.get("dbPassword"); String dBUrl = (String)options.get("dbURL"); String dBDriver = (String)options.get("dbDriver");Connection con = null; try { //loading driver Class.forName (dBDriver).newInstance(); con = DriverManager.getConnection (dBUrl, dBUser, dBPassword); } catch (Exception e) { LOGGER.error("Error when creating database connection" + e); e.printStackTrace(); } finally { } return con; } }The abort() method of the login module will be invoked if something went wrong within the login() or commit() method execution. In this kind of situation, We can not say that the authentication process was successfully completed and the required clean up operations can be done within the abort() method, if the authentication process encountered a failure.We can utilise the ‘options’ map which was initialise within the initialize() method of the login module to get the configuration information declared within the ‘jass.config’ file. You can come up with a good technique to get JDBC connection object. I did not concentrate on that with in this tutorial and only wanted to show you the mechanism, How the things should be done.By now, We have completed the thing which are required for basic JAAS authentication module. Next, We should configure our security constraints in web.xml file. <login-config> <auth-method>FORM</auth-method> <realm-name>rainyDay</realm-name> <form-login-config> <form-login-page>/login.jsp</form-login-page> <form-error-page>/error.jsp</form-error-page> </form-login-config> </login-config> <security-role> <role-name>*</role-name> </security-role> <security-constraint> <web-resource-collection> <web-resource-name>Rainy day</web-resource-name> <url-pattern>/</url-pattern> <http-method>POST</http-method> <http-method>GET</http-method> </web-resource-collection> <auth-constraint> <role-name>*</role-name> </auth-constraint> </security-constraint> With the above security constraints, if some request comes to a particular resource in the protected area of the application with out the authentication, the request will be redirected to the ‘login’ page. Next, I will show you the simple HTML form which invokes our login module with the submission of the form. <form id="loginForm" name="loginForm" method="post" action="j_security_check"> User Name : <input id="username" type="text" name="j_username" class="textbox"></input> Password : <input id="password" type="password" name="j_password" class="textbox"></input> <input name="login" type="submit" value="LOGIN" id="submit" class="button blue"> </form> So, We are done with that.This is very basic implementation of JAAS. The advantage of this kind of JAAS module is, We can switch to a different login module implementation just with a single configuration change and without doing any modification to our existing code. And also this is container independent. If You want to deploy this with jBoss server, instead of ‘jass.config’, You can use ‘login-config.xml’ file in jboss conf folder. As I promised you to explain, How to invoke this kind of login module explicitly, here it is. There are some circumstances, We need to authenticate a particular user with pragmatically, but still We should use our implemented login module. In this kind of situation, the big problem is providing user identities (user name, password etc) to the our login module. In the above case, We used a ‘CallbackHandler’ class which is ‘JAASCallbackHander’ provided by apache catalina. But, Here We can not use and We have to implement our own call back handler class.JAASCallbackHandler.java package com.rainyday.server.login;import java.io.IOException;import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException;import org.apache.log4j.Logger;/** * @author semika * */ public class JAASCallbackHandler implements CallbackHandler {private static final Logger LOGGER = Logger.getLogger(JAASCallbackHandler.class); private String username = null; private String password = null; /** * @param username * @param password */ public JAASCallbackHandler(String username, String password) { this.username = username; this.password = password; }@Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { LOGGER.info("Callback Handler invoked "); for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { NameCallback nameCallback = (NameCallback) callbacks[i]; nameCallback.setName(username); } else if (callbacks[i] instanceof PasswordCallback) { PasswordCallback passwordCallback = (PasswordCallback) callbacks[i]; passwordCallback.setPassword(password.toCharArray()); } else { throw new UnsupportedCallbackException(callbacks[i], "The submitted Callback is unsupported"); } } } }Next, We have to create an instance of ‘ LoginContext’ to invoke the authentication explicitly. LoginContext lc = null; try { lc = new LoginContext("rainyDay", new JAASCallbackHandler(username, password)); lc.login(); //get the subject. Subject subject = lc.getSubject(); //get principals subject.getPrincipals(); LOGGER.info("established new logincontext"); } catch (LoginException e) { LOGGER.error("Authentication failed " + e); }If We end up with the execution of above code without any exception, that implies the authentication was succeeded. If an exception was encountered, authentication has failed.That’s all from this tutorials. http://docs.oracle.com/javaee/1.4/tutorial/doc/Security5.html was a good tutorial for me to understand login authentication. Reference: Java form based authentication from our JCG partner Semika loku kaluge at the Code Box blog....
software-development-2-logo

Class diagram generation from Java source

UMLGraph allows the declarative specification and drawing of UML class and sequence diagrams. The specification is done in text diagrams, that are then transformed into the appropriate graphical representations.UMLGraph is implemented as a javadoc doclet (a program satisfying the doclet API that specifies the content and format of the output generated by the javadoc tool). Furthermore, the output of UMLGraph needs to be post-processed with the Graphviz dot program. Therefore, to draw class diagrams with UMLGraph class you will need to have javadoc and Graphviz installed on your computer. Maven plugin details UMLGraph can be easily integrated with existing maven based application. Below is the maven plugin details which needs to be configured: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <configuration> <doclet>org.umlgraph.doclet.UmlGraphDoc</doclet> <docletArtifact> <groupId>org.umlgraph</groupId> <artifactId>doclet</artifactId> <version>5.1</version> </docletArtifact> <additionalparam>-horizontal -attributes -enumconstants -enumerations -operations -types -visibility -inferrel -inferdep -hide java.* -inferrel -collpackages java.util.*</additionalparam> <show>public</show> </configuration> </plugin> UMLGraph depends upon Graphviz which must be already installed on the machine. Also in the above maven setting if you configure ‘GRAPHVIZ_HOME’ environment variable you need not specify the docletpath in plugin details. Steps to configure UMLGraphDownload and install Graphviz Set GRAPHVIZ_HOME environment variable. Add the above plugin details in your POM.xml, configure additionalparams per your need. execute ‘mvn javadoc:javadoc’.Sample  Below is the sample generated using above configuration over our Pizza entity pizza_class_diagram.pngMore configuration You can configure this diagram per your needs. Please refer UMLGraph class diagram options for more configuration. Reference: Class diagram generation from Java source from our JCG partner Abhishek Jain at the NS.Infra blog....
eclipse-logo

Eclipse Community Survey 2012

Each year we survey the Eclipse community to gather some insight into what developers are doing with Eclipse and open source. We have published the results and the detailed data is available [xls] [ods]. Embedded version of the report is at the end of this post. Each year there are always some key trends shown in the results [2011 results]. Here are some insights that appeared for me: 1. Git Momentum Continues to Grow Git definitely has the momentum in the source code management market. Git/Github usage increased from 13% (2011) to 27% (2012). Subversion continues to decline but is still the most popular. For the first time this year we broke out Git and Github. I was surprised to see the vast majority of people specify Git (23%) and only 4.5% specify GitHub. This seems to show a lot of internal Git usage. Potentially a great opportunity for tool providers. 2. Maven Usage Accelerating Maven usage increased from 31% (2011) to 42% (2012). This might be a reflection on better integration with Eclipse and Maven. If so, kudos to the m2eclipse project team and Tycho. 3. Spring and EJBs continue to be popular server frameworks. Equinox and OSGi increasing too. Both Spring and EJBs continue to be the most popular frameworks for people doing server side development. Spring continues to be the most popular but EJBs gain some ground in 2012. It was great to see Equinox and OSGi runtimes almost double their usage from 6.8% (2011) to 12.3% (2012) 4. Mobile computing = Android + iOS Not surprisingly, mobile computing is dominated by Android and iOS. More people have deployed mobile applications, 43% have developed internal or external applications, compared to 35% in 2011. Android and Apple iOS continue to dominate as the key platforms. It is a bit surprising that more developers are not using cross platform frameworks. 60% claim to use only the Mobile OS SDK. jQuery Mobile (28.6%) and PhoneGap (17.9%) are the most popular mobile frameworks. 5. What motivates a developer? This year we asked some questions to explore what motivates a developer to participate in open source and spend their free time building applications Motivation to participate in open source projects seems to be driven by 1) sense of responsibility – 54% stated they participate to ‘give back and support’ and 36% due to their belief in the FOSS ethos, 2) learning – 36% claim it is a great way to learn new technologies, and 3) improving the project – 33% claim they participate due to a needed feature or bug fix. Somewhat surprisingly only 11% claimed it was due to being paid to contribute and 6% was an effective way to promote consulting business. We also asked how many developers build software/applications in their free time, outside of work. I was a bit surprised that 84% claimed to spend some amount of personal time developing software. The key reason is to learn new technologies, 74% answered they ‘enjoy programming and learning new technologies’ and 71% ‘keep my skills sharp’. An important lesson for anyone in the software industry that is targeting developers: Make it easy for developer to learn your technology. 6. Corporate policies towards open source becoming more positive Each year we ask what is the corporate policy towards open source participation. It is nice to see we are seeing movement towards more positive policies towards contributions and participation. 61% reported their corporate policies allowed them to actively participate in open source projects compared to 58% in 2011. We definitely need to get more companies to allow active participation but at least we are moving in the right direction. Thank you to everyone that participate in the survey. I always enjoy seeing the results. Please feel free to leave a comment on what you find interesting in the results. Eclipse survey 2012 report [final] View more from IanSkerrett Reference: Eclipse Community Survey Result for 2012 from our JCG partner Ian Skerrett at the Ian Skerrett’s blog blog....
software-development-2-logo

Two Years of Experience Doesn’t make you “Senior”

Two years of experience doesn’t make you “senior”. Except maybe in high school. I don’t mean this in a negative sort of way. I mean it in a trying-to-help-you-out sort of way. I’ve worked for a relatively small number of companies in my twenty-plus years of professional life. Small by the software industry’s standards, anyway. I’ve been involved in the hiring process in every job I’ve had. In most cases, I’ve been involved in the full process: assembling the job description, pruning through cover letters and resumes, interviewing, and making recommendations to hire. In my opinion, pruning through cover letters and resumes is the hardest part. There have been times when I’ve literally received more than a thousand applications for a single job posting. In general, the first step is prune that list down to a manageable number (say a dozen or so) of people that you can talk to on the phone. From that list, you hope to narrow it down to a short list (e.g. four or five) of people that you can bring in for a face-to-face interview. You can’t really get to know somebody from a resume and cover letter; they’re used by an employer to sort out who they want to get to know. Winnowing a thousand applications into a dozen or so requires some tricks. I tend to look for two things in an applicant: do they have the skills, and do they pay attention to detail. I don’t care if a resume is printed on cobalt blue paper. I don’t care if it uses a fancy font (though I do care if the selected font makes it difficult to read). I don’t care if it’s presented in some neat-o origami. I don’t care if you won an Olympic gold medal. Actually, I do care about the Olympic gold medal: that’s pretty cool, but it’s still not enough to get you to the next round. The cover letter and resume must highlight relevant skills. I expect that an application for a job lists at least most of the skills required to do that job. The cover letter and resume should be grammatically correct and all words should be spelled correctly. I can read in both correct and American English. Pick one. On the topic of detail, let me return to the title of this post: Two Years of Experience Doesn’t make you “Senior”. Do not tell me that you graduated from college or university two years ago and have been working as a “senior” anything in the field. With two years of experience and a little luck, you may wind up as a “lead” developer; but you’re not senior. You need a few more years of real industry experience before you can call yourself senior. If you’re a young person just starting out in this business, I give you this advice: don’t oversell yourself, represent yourself honestly, pay attention to the details, and do a little research on the companies you’re applying to. The software industry values potential. Reference: Two Years of Experience Doesn’t make you “Senior” from our JCG partner Wayne Beaton at the Eclipse Hints, Tips, and Random Musings blog....
agile-logo

Are Agile plans Better because they are Feature-Based?

In Agile Estimating and Planning, Mike Cohn quotes Jim Highsmith on why Agile projects are better: “One of the things I keep telling people is that agile planning is “better” planning because it utilizes features (stories, etc.) rather than tasks. It is easy to plan an entire project using standard tasks without really understanding the product being built. When planning by feature, the team has a much better understanding of the product.” In the original post on a Yahoo mailing group,Highsmith also says “Sometimes key people in the agile movement have exaggerated at times to get noticed, I’ve done it myself at times–gone a little overboard to make a point. People then take this up and push it too far.” This is clearly one of those times. Activity-based Planning vs. Feature-based Planning The argument runs like this. Activity-based plans described in a WBS and Gantt charts are built up from “standardized tasks”. These tasks or activities are not directly tied to the features that the customer wants or needs – they just describe the technical work that the development team needs to do, work that doesn’t make sense to the other stakeholders. According to Highsmith, you can build a plan like this without understanding what the software that you are building is actually supposed to do, and without understanding what is important to the customer. An Agile plan, working from a feature backlog, is better because it “forces the team to think about the product at the right level – the features”. I don’t think that I have worked on a software development project, planned any which way, where we didn’t think about and plan out the features that the customer wanted. Where we didn’t track and manage the activities needed to design, build and deliver software with these features, including the behind-the-scenes engineering work and heavy lifting: defining the architecture, setting up the development and build and test environments and tools, evaluating and implementing or building frameworks and libraries and other plumbing, defining APIs and taking care of integration with other systems and databases, security work and performance work and operations work and system and integration testing and especially dealing with outside dependencies. Some of this work won’t make sense to the customer. It’s not the kind of work that is captured in a feature list. But that doesn’t mean that you should pretend that it doesn’t need to be done and it doesn’t mean that you shouldn’t track it in your plans. Good project planning makes explicit the features that the customer cares about and when they will be worked on, and the important technical work that needs to get done. It has to reflect how the team thinks and works. Activity-Based Planning is so Wrong in so very many Ways In one of the first chapters, “Why Planning Fails”, Cohn enumerates the weaknesses of activity-based planning. First, most activity-based planners don’t bother to prioritize the work that needs to be done by what the customer wants or needs. This is because they assume that everything in the scope needs to be, and will be, done. So activities are scheduled in a way that is convenient for the development team. Which means that when the team inevitably realizes that they are over budget and won’t hit their schedule, they’ll have to cut features that are important to the customer – more important than the work that they’ve already wasted time working on. Maybe. But there’s nothing stopping teams using activity-based planning from sequencing the work by customer priority and by technical dependencies and technical risk – which is what all teams, including Agile teams, have to do. This is how teams work when they follow a Spiral lifecycle, and teams that deliver work in incremental releases using Phased/Staged Delivery, or teams that Design and Build to Schedule, making sure that they get the high-priority work done early in order to hit a hard deadline. All of these are well-known software project planning and delivery approaches which are described in Steve McConnell’s Rapid Development and other books. Everyone that I know who delivers projects in a “traditional, plan-driven” way follows one of these methods, because they know that that a pure, naïve, plan-everything-upfront serial Waterfall model doesn’t work in the real world. So we can stop pretending otherwise. Another criticism of activity-based planning is that it isn’t possible to accurately and efficiently define all of the work and all of the detailed dependencies for a software development project far in advance. Of course it isn’t. This is what Rolling Wave planning is for – lay out the major project milestones and phases and dependencies, and plan the next release or next few months/weeks/whatever in detail as you move forward. Although Cohn does a good job of explaining Rolling Wave planning in the context of Agile projects, it’s been a generally-recognized good planning practice for any kind of project for a long time now. Agile plans aren’t better because they are Feature-Based These, and the other arguments against activity-based planning in this book, are examples of a tired rhetorical technique that Glen Alleman describes perfectly as: “Tell a story of someone doing dumb things on purpose and then give an example of how to correct the outcome using an agile method”. Sure, a lot of Waterfall projects are badly run. And, yeah, sure, an Agile project has a better chance of succeeding over a poorly-planned, badly-managed, serial Waterfall project. But it’s not because Agile planning is feature-based or because activity-based planning is wrong. People can do dumb things no matter what approach they follow. The real power in Agile planning is in explicitly recognizing change and continuously managing uncertainty and risk through short iterations. Fortunately, that’s what the rest of Cohn’s book is about. Reference: Are Agile plans Better because they are Feature-Based? from our JCG partner Jim Bird at the Building Real Software blog....
java-interview-questions-answers

Testing Abstract Classes and Template Method Pattern

From wikipedia “A template method defines the program skeleton of an algorithm. One or more of the algorithm steps can be overridden by subclasses to allow differing behaviors while ensuring that the overarching algorithm is still followed”. Typically this pattern is composed by two or more classes, one that is an abstract class providing template methods (non-abstract) that have calls to abstract methods implemented by one or more concrete subclasses. Often template abstract class and concrete implementations reside in the same project, but depending on the scope of the project, these concrete objects will be implemented into another project. In this post we are going to see how to test template method pattern when concrete classes are implemented on external project, or more general how to test abstract classes. Let’s see a simple example of template method pattern. Consider a class which is responsible of receiving a vector of integers and calculate the Euclidean norm. These integers could be received from multiple sources, and is left to each project to provide a way to obtain them. The template class looks like: public abstract class AbstractCalculator {public double euclideanNorm() {int[] vector = this.read();int total = 0;for(int element:vector) { total+= (element*element); }return Math.sqrt(total); }public abstract int[] read(); }Now another project could extend previous class and make an implementation of abstract calculator by providing an implementation of read() method . public class ConsoleCalculator extends AbstractCalculator {public int[] read() {int [] data = new int[0];Scanner scanner = new Scanner(System.in);//data = read requried data from consolereturn data;}}Developer that has written a concrete implementation will test only read() method, he can “trust” that developer of abstract class has tested non-abstract methods. But how are we going to write unit tests over calculate method if class is abstract and an implementation of read() method is required? The first approach could be creating a fake implementation: public class FakeCalculator extends AbstractCalculator {private int[] data;public FakeCalculator(int[] data) { this.data = data; }public int[] read() { return this.data; }}This is not a bad approach, but has some disadvantages:Test will be less readable, readers should know the existence of these fake classes and must know exactly what are they doing. As a test writer you will spend time in implementing fake classes, in this case it is simple, but your project could have more than one abstract class without implementation, or even with more than one abstract method. Behaviour of fake classes are “hard-coded”.A better way is using Mockito to mock only abstract method meanwhile implementation of non-abstract methods are called. public class WhenCalculatingEuclideanNorm {@Test public void should_calculate_correctly() {AbstractCalculator abstractCalculator = mock(AbstractCalculator.class, Mockito.CALLS_REAL_METHODS);doReturn(new int[]{2,2}).when(abstractCalculator).read(); assertThat(abstractCalculator.euclideanNorm(), is(2.8284271247461903));}@Test public void should_calculate_correctly_with_negative_values() {AbstractCalculator abstractCalculator = mock(AbstractCalculator.class, Mockito.CALLS_REAL_METHODS);doReturn(new int[]{-2,-2}).when(abstractCalculator).read(); assertThat(abstractCalculator.euclideanNorm(), is(2.8284271247461903));}}Mockito simplifies the testing of abstract classes by calling real methods, and only stubbing abstract methods. See that in this case because we are calling real methods by default, instead of using the typical when() then() structure, doReturn schema must be used. Of course this approach can be only used if your project does not contain a concrete implementation of algorithm or your project will be a part of a 3rd party library on another project. In the other cases the best way of attacking the problem is by testing the implemented class. Download sourcecode Reference: Testing Abstract Classes (and Template Method Pattern in Particular) from our JCG partner Alex Soto at the One Jar To Rule Them All blog....
software-development-2-logo

Software Principles are like some Life Principles

Software principles are useful tools for design and implementation and they help us produce quality products. However, software principles can be compromised at times. They don’t always have to be followed as there are exceptions to the rule. In some ways, they are similar to some life principles, and this blog explores that idea.Software and LifeIn life we have ethics and morals that we live by. Ethics and morals manifest themselves as life principles. They give us a framework to become better people, respect one another, and ultimately improve our quality of life.In the software industry we have software design principles. They are rules we operate under in order to make the products we develop elegant, easy to understand, and maintainable. Software products run our economy or make our day to day lives easier, and software principles play a large role in allowing that to happen.However, software design principles are not meant to be dogmatic. They are not meant to be strictly adhered to. The use of software principles should be evaluated within the prism of trade offs. Software principles are essentially rules of thumbs and can be broken if it’s the most pragmatic thing to do.Software principles are like some life principles . . . but unlike others. To illustrate my point, let’s consider some life principles that can be considered absolute, i.e, should never be broken no matter what the circumstances.Don’t Cheat, and Be NiceTake the rule “Don’t cheat.” Under no circumstances would I teach my son that it is permissible to cheat. It’s not OK to cheat on a test at school. It’s not OK to cheat on your taxes, and its not OK to cheat on a board game at home. No matter what the context, big or small, cheating is not beneficial. It only hurts others and ultimately your self. Software principles aren’t like the cheating principle.Another example would be “Never treat a person as a means to an end.” It is unethical to use a person strictly as a means to an end with disregard to their humanity. People should be treated as human beings, not as objects. Under no circumstances, would I teach my child to “use” someone just for the sake of personal gain and devoid of respect. Software principles aren’t like ethical principles . . . we can break them if needed.So what are software principles like then, and what software principles am I talking about? Most life principles we live by are general rules of thumb, they are not absolutes. Software principles are like that. Here are a few examples of what I mean:DRYWe live by the principle of “Always tell the truth”, but this rule doesn’t always apply. Take for example white lies. If your wife asks you, “Do I look fat in this dress?”, you would be asinine to say yes. Most us would say “No honey, you look great!” Even though your beautiful wife may be slightly overweight (no big deal in my eyes, personally.)In software, we have the DRY principle: Don’t Repeat Yourself. This should be something you mostly do and can greatly contribute to clean code. But would you really want to create a full fledged Template or Strategy Method Pattern to save 1 or 2 lines of code? Sometimes violating the DRY principle can avoid excessive pattern usage, which can cripple a project and make code unintelligible. Evaluate the trade offs for DRY and make the best decision.Law Of DemeterHow about the life principle of “Always eat healthy”? Yes, we should eat healthy and watch our diet, in general, so we can live a quality life. But we are allowed to break the rule on holidays and eat the fried turkey and pecan pie. It is permissible to go out with the guys and down some beers and wings once in a while. It’s not going to kill you. If eating unhealthy is the exception, it is fine.The Law of Demeter is a software principle that enables loose coupling and limits the knowledge of one component to another. Following this rule keeps your code understandable and limits dependencies. But even though its called a “law”, it should be viewed more as a guideline. If you are dealing with an anemic object, and just need to get some data, it is permissible to for a client to dig through objects to get what it needs. The alternative would be to blow up the API with several needless methods, which is a documented disadvantage of Law of Demeter.ConclusionWhen designing software, we should understand that software principles should be followed in order to produce quality code. However, use them in a pragmatic manner and don’t pursue a software principle so hard that it makes your life and code, miserable. Evaluate your design in terms of trade offs. After all, we certainly have life principles that we don’t always follow, and software principles are the same way. Do what’s best for value added effort and leave the dogma behind.Reference: Software Principles are like some Life Principles from our JCG partner Nirav Assar at the Assar Java Consulting blog....
java-interview-questions-answers

A revolution with Business Activity Monitor (BAM) 2.0

Producing middle ware that is both lean and enterprise worthy is a difficult job. It’s either non-existent or requires innovative thinking (a lot of it) and a lot of going back and forth with your implementations. Very risky business, but if you get it right, it puts you far ahead of anyone else. It’s why we thought of re-writing WSO2 BAM from scratch and taking a leap rather than chugging away slowly by iterative fixing. If you prefer to hear me rather than reading this, please catch a webinar on this at http://bit.ly/xKxm8R.     Diagram coutesy of http://softwarecreation.org/2008/ideas-in-software-development-revolution-vs-evolution-part-1/When you try to monitor your business activities, you need to plug in to your servers and capture events. It sounds easy enough, so what’s the big deal? you may ask. Here’s a few road blocks we hit with our intial BAM 1.x version:Performance – We plug in to our ESBs and App Servers and all metrics were perfect. It nicely showed request counts, response times, etc. It was perfect as long as the load is low. If one server starts sending 1000 events/sec, things started getting ugly. Even worse, if we plug in to a few servers and start getting 1 billion events / day, well, that would have been a nightmare from the word go. We couldn’t even fathom what would happen at that type of scale. Scalability – We need to store events and process them. Sadly, we discovered the hard waye this would mean is we need to scale in many different ways.Event load – We need to scale in terms oh handling large amounts of events. We didn’t have a high performance server, but no matter how good our performance would be, there is still a breaking point. Afterwards, you need to scale. Storage – If you store 1000 events a day, your data will grow. And, all of us hate to delete off old email, to get more inbox space. So naturally, everyone wants to keep their events. Processing power – When you want to analyze events that you collect, a single server can only give you that much of processing power. You need to scale out your analytics. Another, ‘oh, so obvious’ thing that we learnt eventually.Customizability – We provided a lovely set of dashboards that showed all you wanted to know about your server and API metrics. But, no one is ever satisfied with what we they have. They want more. They want to monitor their metrics and analyze their data and put up their own graphs. And, of course, they want to do it now, not in 2 months.In May 2011, we decided to start a whole new initiative to re-write WSO2 BAM from scratch. We analyzed the problem made a few decisions. Here’s a few of them.Divide and conquer – We divided the problem. We have to aggregate, analyze and present data. So we built separate components for each, keeping in mind that we need to scale each individually. We mapped these into the event receiver, analyzer framework and a presentation layer. Data agents are the link between anyone who wants to send events and the BAM server. The WSO2 Carbon platform, allows us to easily uninstall a component from any server. This means we can take the BAM distro, uninstall other components just to make an Event Receiver BAM server. Or to make an Analyzer BAM server. It’s just a click of a button.The 3 main components of BAM 2.0Scalable and fast storage – We chose to use Apache Cassandra as our storage solution. I do not want to argue that it’s the best data store ever. But, it works for us well. It allows us to do fast writes to store a large amount of data, quickly. Also, it’s built to scale. Scaling up Cassandra, takes minutes, not weeks. And scaling up doesn’t mean it’s going to cost you. Also, it’s written in Java, and being a Java house, it allows us to hack around the code. Fast protocol – We chose to use Apache Thrift as our default protocol. There are many arguments against it, but it holds up well for us. It’s fast and it does it’s job. It allows us to maintain sessions, supports a bunch of languages. One key thing was Cassandra uses it as well, allowing us to gain more performance in streaming data into Cassandra without deserializing. Scalable analytics – We chose to write our own analytics language. But, if it doesn’t suit you, you can plugin your own java code. Hadoop is unavoidable when it comes to scaling analytics. So, we decided to have a Hadoop mode for large amounts of data and a non-Hadoop mode, so that anyone can just use BAM without worrying about any Hadoop cluster.  Gadget based dashboards/reports – Drag and drop visualizations are very attractive when you don’t want to spend weeks writing code to visualize. We developed a gadget generator so you can quickly visualize your analyzed data easily.After a couple of milestones, we were able to spin off an alpha. It’s available here: http://dist.wso2.org/products/bam/2.0.0-Alpha/wso2bam-2.0.0-ALPHA.zip. It is not the silver bullet and documentation is still WIP. But, if we haven’t already reached our destination, it’s within our reach now. Reference: A revolution with Business Activity Monitor (BAM) 2.0 from our JCG partner Mackie Mathew at the dev_religion blog....
Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close