Thursday, February 19, 2015

Starting with Apache Maven

Apache Maven is a build or a total project management tool, that scores over its predecessors such as ANT for Java builds, with the following advantages:
  • Useful when Multiple JAR Files are Required for Build
  • Resolving Recursive Dependencies During Build Time
  • Creating Project Structures that are Standardized
  • Building, Publishing and Deployment of Applications
  • Supports Lifecycle of an Application along with Plugins

I have created an alumni project that is a Dynamic Web Archive with a Servlet that says “Hello, Alumni”. 


INSTALLATIONS REQUIRED
Apache Maven 3.2.5
Apache Tomcat 8.0.9
JDK 1.7.0 / JRE 1.7.0
Notepad++ 6.6.7


MAVEN BASICS
1. Setting up Maven
First, Download Apache Maven 3.2.5 from http://maven.apache.org/download.cgi

Next, Set the path variables for M2 and M2_HOME
Set your M2_HOME environment variable to point to the root of Apache Maven installation. Also, M2 environment variable will be point to the bin folder under the Apache Maven installation. For example, if you have installed Apache Maven under d:\apache-maven-3.2.5 – you would have to set the variables as following:
set M2_HOME= d:\apache-maven-3.2.5
set M2= d:\apache-maven-3.2.5\bin

You must additionally set Maven in your path as follows.
set PATH=%PATH%;%M2%

2. Configuring Maven (Creating Project)
Now, run the mvn archetype:generate command form the place where you want to create a web project. Start off with this command to download all templates from the internet. This has to be used initially, so that all known project templates can be downloaded to the local system. It will prompt you at the end of successful execution of this command for a number. Enter the number 529, which is used for ‘maven-archetype-webapp’. Make sure that you have an internet connection otherwise you will not see all archetype listings. Maven Archetype is a templating toolkit that is provided along with Maven.


3. Creating Alumni Servlet
Add a folder ‘java’ under ‘src\main’ before we can code our Java Servlet. Under main add the folders ‘me’, followed by ‘sumithpuri’ followed by ‘maven’ – each under the other; so that the directory structure looks like this:

Now, write the java servlet source file AlumniServlet.java using Notepad++ as follows:


4. Building Alumni Project
If we now try to build the project using ‘mvn compiler:compile’, we will get the following errors, because we have not added the dependent JAR files for Java Servlets.


5. Dependency Management
We can add the dependent JARs so that the project can compile. We can do so in the pom.xml – The explanation for how Maven will download this JAR to the local repository and the details of the POM (Project Object Model) are provided later in this blog.


6. (Re) Building / Compiling the Alumni Project
Use ‘mvn compiler:compile’ to compile the web application.

7. Packaging & Deploying Alumni Project
Modify the web.xml to add the servlet using the following configuration.


User ‘mvn war:war’ to package the web application.


Finally, drop this under Apache Tomcat ‘webapps’ folder and type the url http://localhost:8080/alumni to see the output on the browser as:


NOTE: MAKE SURE YOU RENAME THE DEFAULT INDEX.JSP TO INDEX.BKP TO RENDER SERVLET OUTPUT


DOWNLOADS
You may download the alumni.zip that also contains the alumni.war under target folder to try this out yourself.


CONCLUSION
Maven provides a simple and extensible way to compile, build and deploy applications and allows us to manage the total build life-cycle of applications.


MAVEN THEORY
Maven Co-ordinates
The following are known as the maven co-ordinates (the ones that are the most important) for any project.

groupId: The name with which we can refer group of such projects. e.g.: alumni_project
artifactId: The name with which the JAR or WAR will be created. e.g.: alumni
version: The version number of the current project
package: The package of the resulting classes, usually under src\java. e.g.: me.sumithpuri.maven

Maven Lifecycle
The most important lifecycle stages or phases for a Maven project include the following.
validate – Validates if the project co-ordinates and pom.xml are valid, else generates error
compile – Compiles the project and generates any error it cannot be compiled
test – Unit Tests the code and does not require that the code be packaged
package – Packages and generate the artifact such as JAR
install – Installs the generated artifact, such as JAR in the local repository

Maven Plugins
Maven works in the form of plugins and follows the general format as follows: mvn plugin:goal

Some of the plugins include jar, compiler and surefire. An example of an Maven command is as follows: mvn compiler:compile

Maven Repository (Architecture)
Maven follows a two repository model, wherein it maintains a local repository (which is created when you execute the first maven command). It downloads dependencies from the remote repository onto this local repository and then builds projects. The architecture looks like the following:

  • Maven Project is compiled; It checks in the local repository for dependencies
  • If dependencies do not exist; Maven downloads them from the remote repository 
  • Once dependencies are downloaded; they are installed in the local repository
  • Once all dependencies are met; Maven compiles the code and the project

Project Object Model
Maven is able to achieve the dependency management through the existence of Project Object Model or pom.xml files within each of the modules. At each module level, we can provide pom.xml – that contains the build environment information, build settings information, dependency relationships between pom’s and general project information. Also, there is a concept of inheritance and effective pom (where the effective pom is a resultant of the inheritance hierarchy). 
 
[A Sample POM.xml ]


Super Project Object Model
Located inside the Maven installation is a Super POM (pom.xml), usually in the maven-model-builder-<x.y.z>.jar files which is the under the %M2_HOME%\lib\ folders. This contains the details which all other modules’ POM inherit from. This also contains the location of the remote repository which is by default https://repo.maven.apache.org/maven2 It usually has four main sections – central repository details, plugin repository details, build details and plugin management details.


Sunday, February 15, 2015

REST Using Apache Wink

Representational State Transfer (REST)
Hypermedia as the Engine of Application State (HATEOAS)
  
 
I built this Product Web Service using Apache Wink. It can perform add, update, delete and retrieval of products in memory. I intend to explain the basics of REST using Apache Wink using this. REST stands for Representational State Transfer. REST is based on the concepts of Roy Fielding’s dissertation work as part of his thesis. It works on the HTTP protocol and has the following differences when compared to SOAP:
  • Works on HTTP protocol, as compared to SOAP which creates their own protocol
  • Uses HTTP GET, PUT, POST, DELETE as compared to SOAP which uses only POST
  • It uses the HTTP infrastructure, whereas SOAP is transport neutral     
  • The producer and consumer are aware of the content being exchanged     
  • It does not support many Non Functional Requirements or any WS-* Standards

INSTALLATIONS REQUIRED
Eclipse 4.2.0
Apache Wink 1.4.0
Apache Tomcat 8.0.9
JDK 1.7.0 / JRE 1.7.0
 

SERVER / WEB SERVICE
The steps to build the web service using Apache Wink are given below:

1.     Create a Dynamic Web Project in Eclipse

2.     Build the Core Application that performs CRUD 
 /**   
  *    
  */   
  package me.sumithpuri.rest.persistence;   
     
     
  import java.util.ArrayList;   
  import java.util.List;   
     
  import me.sumithpuri.rest.vo.Product;   
     
  /**   
  * @author sumith_puri   
  *   
  */   
  public class ProductPersistenceManager {   
     
    private List<Product> productDatabase = new ArrayList<Product>();   
    private static ProductPersistenceManager persistenceManager;   
    private static int id=0;   
       
    private ProductPersistenceManager() {   
          
    }   
       
    public void add(Product product) {   
          
       System.out.println("database: added one product");   
          
       // atomic id creation   
       id++;   
       product.setId(id);   
       productDatabase.add(product);   
    }   
       
    public List<Product> get() {   
       System.out.println("database: retrieved all products");   
       return productDatabase;   
    }   
       
    public void update(long productId, String productName) {   
       System.out.println("database: modified one product");   
          
       for(int i=0;i<productDatabase.size();i++) {   
            
         Product product = productDatabase.get(i);   
         if(product.getId()==productId) {   
            product.setName(productName);   
            productDatabase.remove(i);   
            productDatabase.add(i,product);   
         }   
       }   
       return;   
    }   
       
    public void delete(long productId) {   
       System.out.println("database: deleted one product");   
          
       for(int i=0;i<productDatabase.size();i++) {   
            
         Product product = productDatabase.get(i);   
         if(product.getId()==productId) productDatabase.remove(i);   
       }   
       return;   
    }   
       
    public static ProductPersistenceManager getInstance() {   
          
       if(persistenceManager==null) {   
         synchronized(ProductPersistenceManager.class) {   
            if(persistenceManager==null) {   
              persistenceManager = new ProductPersistenceManager();   
            }   
         }   
       }   
       return persistenceManager;   
    }   
  }   

3. Add the Supporting JAR files in the Build Path

4. Create the REST Web Service using Apache Wink (GET, POST, DELETE, PUT)
 package me.sumithpuri.rest.webservice;  
   
   
 import java.util.List;  
   
 import javax.ws.rs.DELETE;  
 import javax.ws.rs.GET;  
 import javax.ws.rs.POST;  
 import javax.ws.rs.PUT;  
 import javax.ws.rs.Path;  
 import javax.ws.rs.PathParam;  
 import javax.ws.rs.Produces;  
 import javax.ws.rs.core.MediaType;  
   
 import me.sumithpuri.rest.persistence.ProductPersistenceManager;  
 import me.sumithpuri.rest.vo.Product;  
   
 /**  
  * @author sumith_puri  
  *  
  */  
 @Path("product")  
 public class ProductWebService {  
   
     ProductPersistenceManager persistenceManager = ProductPersistenceManager.getInstance();  
       
     @GET  
     @Produces(MediaType.TEXT_PLAIN)  
     public String getProducts() {  
           
         List<Product> products = persistenceManager.get();  
         String productList = new String();  
           
         for(Product producti: products) {  
             productList+=producti.toString() + "\n";  
         }  
           
         // return as plain text - other types include xml, json  
         return productList;  
     }  
       
     @POST  
     public String addProducts(String productStr) {  
           
         Product product = new Product();  
         product.setName(productStr);  
         persistenceManager.add(product);  
           
         return productStr;  
     }  
       
     @DELETE  
     @Path("/{id}")  
     public void deleteProduct(@PathParam(value="id") long id) {  
           
         persistenceManager.delete(id);  
         return;  
     }  
       
     @PUT  
     @Path("/{id}")  
     public void modifyProduct(@PathParam(value="id") long id, String productName) {  
           
         persistenceManager.update(id, productName);  
         return;  
     }  
 }  
   

5.  Configure Application for Apache Wink
To allow Apache Wink to locate this service as a REST web service, you can either define an additional class or configure an application file. We are using an application to mention all our web service.

You can place this under WEB-INF/ and name the file as simply ‘application’ (without any extension).
 me.sumithpuri.rest.webservice.ProductWebService  

Next, you need to specify the servlet related configuration for allowing Apache Wink REST Servlet to locate this appliatiocn configuration, by specifying the location of ‘application’ as the parameter ‘applicationConfigLocation’ in WEB-INF/web.xml
 <?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_3_0.xsd" id="WebApp_ID" version="3.0">  
  <display-name>products</display-name>  
  <servlet>  
   <servlet-name>restService</servlet-name>  
   <servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>  
   <init-param>  
    <param-name>applicationConfigLocation</param-name>  
    <param-value>/WEB-INF/application</param-value>  
   </init-param>  
  </servlet>  
  <servlet-mapping>  
   <servlet-name>restService</servlet-name>  
   <url-pattern>/rest/*</url-pattern>  
  </servlet-mapping>  
 </web-app>  

6. Deploy as Apache Tomcat Web App, Directly

CLIENT / WEB SERVICE CLIENT
The steps to test the web service or write a REST client are as follows:

1. Create a Java Project in Eclipse
2. Include the Support Client JAR files in the Classpath

3. Build the client to test or access GET method
4. Build the client to test or access POST method
5. Build the client to test or access DELETE method
6. Build the client to test or access PUT method
 package me.sumithpuri.rest.client;  
   
 import javax.ws.rs.core.MediaType;  
   
 import org.apache.wink.client.ClientConfig;  
 import org.apache.wink.client.Resource;  
 import org.apache.wink.client.RestClient;  
   
   
 /**  
  * @author sumith_puri  
  *  
  */  
 class ProductRESTClient {  
   
     static String REST_WEB_SERVICE="http://localhost:8080/products/rest/product";  
     static ClientConfig clientConfig = new ClientConfig();  
   
     /**  
      * @param args  
      */  
     public static void main(String[] args) throws Exception {  
                   
         try {  
               
             ProductRESTClient restClient = new ProductRESTClient();              
             System.out.println("Apache Wink Based REST Client");  
             System.out.println("Sumith Kumar Puri (c) 2015");  
             System.out.println("=============================");  
               
             restClient.configureClient();  
             System.out.println();  
               
             restClient.invokeGET();  
             System.out.println();  
                       
             String product="Sumith Puri" + (int) (Math.random()*9999);  
             restClient.invokePOST(product);  
               
             System.out.println();  
             product="Sumith Puri" + (int) (Math.random()*9999);  
             restClient.invokePOST(product);  
               
             System.out.println();  
             product="Sumith Puri" + (int) (Math.random()*9999);  
             restClient.invokePOST(product);  
               
             System.out.println();  
             product="Sumith Puri" + (int) (Math.random()*9999);  
             restClient.invokePOST(product);  
               
             System.out.println();  
             restClient.invokeGET();  
               
             System.out.println();  
             restClient.invokeDELETE(2L);  
               
             System.out.println();  
             restClient.invokeGET();  
               
             System.out.println();  
             product="Sumith Puri" + (int) (Math.random()*9999);  
             restClient.invokePOST(product);  
               
             System.out.println();  
             product="Sumith Puri" + (int) (Math.random()*9999);  
             restClient.invokePOST(product);  
   
             System.out.println();  
             restClient.invokeDELETE(4L);  
   
             System.out.println();  
             restClient.invokeGET();  
               
             System.out.println();  
             restClient.invokePUT(3L,"Sumith Puri");  
               
             System.out.println();  
             restClient.invokeGET();  
         } catch (Exception e) {  
               
             e.printStackTrace();  
         }  
     }  
       
   
     public void configureClient() {  
   
     }  
       
     public void invokeGET() {  
           
         System.out.println("Testing GET command....");      
         RestClient restClient = new RestClient(clientConfig);  
         Resource resource = restClient.resource(REST_WEB_SERVICE);  
         String response = resource.accept("text/plain").get(String.class);  
         System.out.printf(response);  
         System.out.println("...GET command is successful");  
     }  
       
     public void invokePOST(String product) {  
           
         System.out.println("Testing POST command...");  
         RestClient restClient = new RestClient(clientConfig);  
         Resource resource = restClient.resource(REST_WEB_SERVICE);  
         resource.contentType(MediaType.TEXT_PLAIN).accept(MediaType.TEXT_PLAIN).post(String.class,product);  
         System.out.println("...POST command is successful");  
     }  
   
       
     public void invokePUT(Long id, String productName) {  
           
         System.out.println("Testing PUT command...");  
         RestClient restClient = new RestClient(clientConfig);  
         Resource resource = restClient.resource(REST_WEB_SERVICE+"/"+id);  
         resource.contentType(MediaType.TEXT_PLAIN).accept(MediaType.TEXT_PLAIN).put(String.class, productName);  
         System.out.println("...PUT command is successful");  
     }  
       
     public void invokeDELETE(Long id) {  
           
         System.out.println("Testing DELETE command...");  
         RestClient restClient = new RestClient(clientConfig);  
         Resource resource = restClient.resource(REST_WEB_SERVICE+"/"+id);  
         resource.contentType(MediaType.TEXT_PLAIN).accept(MediaType.TEXT_PLAIN).delete();  
         System.out.println("...DELETE command is successful");  
     }  
 }  
   



OUTPUT (FIRST ACCESS)
Apache Wink Based REST Client
Sumith Kumar Puri (c) 2015
=============================

Testing GET command....
...GET command is successful

Testing POST command...
...POST command is successful

Testing POST command...
...POST command is successful

Testing GET command....
ID:1, NAME: Sumith Puri3169
ID:2, NAME: Sumith Puri6052
...GET command is successful

Testing DELETE command...
...DELETE command is successful

Testing GET command....
ID:1, NAME: Sumith Puri3169
...GET command is successful

Testing POST command...
...POST command is successful

Testing POST command...
...POST command is successful

Testing DELETE command...
...DELETE command is successful

Testing GET command....
ID:1, NAME: Sumith Puri3169
ID:3, NAME: Sumith Puri732
...GET command is successful

Testing PUT command...
...PUT command is successful

Testing GET command....
ID:1, NAME: Sumith Puri3169
ID:3, NAME: Sumith Puri
...GET command is successful


DOWNLOADS
You may download the products.war (including source) web service as well as the products-client.jar (including source).


CONCLUSION
In this blog, you have seen how to build REST web services using Apache Wink for basic data types. Next, I will blog on how to include Jackson or Jettison as the stream reader or stream writer JSON libraries, so that we can read and write complex or application object types. It will be titled ‘REST Using Apache Wink and Jackson/Jettison’.


[GitHub Repository for Code Samples]
https://github.com/sumithpuri/skp-code-marathon-hochiminh
 

Tuesday, February 3, 2015

Tic-Tac-Toe (Minimax Algorithm) in Java

I Implemented the Classic Two-Player Tic-Tac-Toe using Minimax Algorithm in Java.

You may Download it From Here and Modify as Required.

Do You Wanna Play It Now? I Built an User Interface For This > Can You Beat Me? Hope to Port This, To Be My First Android App Ever in Life! Wait for Updates.