Wednesday, November 19, 2014

JSON/Java Binding

In this blog, I'll show you how to bind JSON data to Java objects.

Let's start with a simple books example. The following JSON file contains a list of books:

books.json:
[
{"ibsn":"978-0486400778", "author":"Mark Twain", "title":"The Adventures of Tom Sawyer"},
{"ibsn":"978-0486280615", "author":"Mark Twain", "title":"Adventures of Huckleberry Finn"}
]
To map this data to a list of Book objects, first define a Book POJO:
package com.noushin.databinding;

public class Book {
    private String ibsn;
    private String title;
    private String author;
    
    public String getIbsn() {
        return ibsn;
    }
    public void setIbsn(String ibsn) {
        this.ibsn = ibsn;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    
    public String toString() {
        return String.format("Book ibsn: %s, title: %, author: %s ", ibsn, title, author);
    }
}

I'll be using Jackson for data binding, so add the proper dependency to your pom file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.noushin</groupId>
    <artifactId>databinding</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>databinding</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.3.3</version>
        </dependency>
    </dependencies>
</project>

And the code to perform the transformation:
package com.noushin.databinding;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

public class BookService {

    public List<Book> transform(String jsonFileName) throws IOException, URISyntaxException {
        byte[] jsonData = Files.readAllBytes(Paths.get(ClassLoader.getSystemResource(jsonFileName).toURI()));
        ObjectMapper mapper = new ObjectMapper();
        List<Book> books = mapper.readValue(jsonData, new TypeReference<List<Book>>(){});
        System.out.println("Transformed " + + books.size() + " books.");
        return books;
    }
}

And finally, here is your JUnit testcase to verify the transformation:
package com.noushin.databinding;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;

import org.junit.Test;

import junit.framework.TestCase;

public class BookServiceTest extends TestCase {

    @Test
    public void testBookService() {
        BookService bookService = new BookService();
        try {
            List<Book> books = bookService.transform("books.json");
            assertTrue(books.get(0).getAuthor().equals("Mark Twain"));
        } 
        catch (IOException e) {
            e.printStackTrace();
        } 
        catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }
    

Wednesday, October 8, 2014

Jython - Calling Python from Java

Let's say you do most of your development in Java, however, there is some existing Python code you need to reuse. In this post, I'll show you how to use Jython to call Python from Java.

Write a Java wrapper class:
public class JythonDemo {

    public int testMe(int num1, int num2) {
        PythonInterpreter python = new PythonInterpreter();

        python.set("num1", num1);
        python.set("num2", num2);
        python.exec("num3 = num1 + num2");
        PyObject num3 = python.get("num3");

        return Integer.parseInt(num3.toString());

    }
}

If using Maven, here is your pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.noushin</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>demo</name>
    <description>Demo</description>

    <dependencies>
        <dependency>
            <groupId>org.python</groupId>
            <artifactId>jython-standalone</artifactId>
            <version>2.5.2</version>
        </dependency>
    </dependencies>

</project>
Just call testMe(), and that'll run your Python code:
JythonDemo jythonDemo = new JythonDemo();
int result = jythonDemo.testMe();


Wednesday, June 4, 2014

Sending emails with attachments

In this example, I will show you how to use Java and Spring to send an email with attachments. Here is the main class to start things off:
package com.noushin.spring.email;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;

import javax.mail.MessagingException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Main class to demonstrate sending an email with attachments.
 * 
 * @author nbashir
 * 
 */
public class EmailMain {

   public static void main(String[] args) {
      ApplicationContext ctx = new ClassPathXmlApplicationContext("application-context.xml");
      try {
         if (ctx != null) {
            Emailer emailer = ctx.getBean(Emailer.class);
            Collection<File> attachments = new ArrayList<File>();
            File attachment = new File("/home/nbashir/file.txt");
            attachments.add(attachment);
            emailer.sendEmail("Test Email", "Please see attached file(s).", attachments);
         }
      }
      catch (MessagingException me) {
         // TODO Auto-generated catch block
         me.printStackTrace();
      }
      catch (Exception ex) {
         ex.printStackTrace();
      }
   }
}
And Emailer class that generates an Email message, attaches files to it, and delivers.
package com.noushin.spring.email;

import java.io.File;
import java.util.Collection;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

@Component
public class Emailer {

   @Autowired
   @Qualifier("mailSender")
   private JavaMailSender mailSender;

   @Value("${email.recipients}")
   private String emailRecipients;
   @Value("${email.from}")
   private String emailFrom;
   @Value("${email.reply.to}")
   private String emailReplyTo;

   /**
    * Send an email with attachments
    * 
    * @param subject email's subject line
    * @param body email's body
    * @param attachments list of attachments
    * 
    * @throws MessagingException 
    */
   public void sendEmail(String subject, String body, Collection<File> attachments) throws MessagingException {

      MimeMessage message = mailSender.createMimeMessage();
      MimeMessageHelper msgHelper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED);

      String[] recipients = getRecipients(emailRecipients);
      if (recipients != null) {
         for (int i = 0; i < recipients.length; i++)
            msgHelper.addTo(recipients[i]);
      }
      msgHelper.setFrom(emailFrom);
      msgHelper.setReplyTo(emailReplyTo);
      msgHelper.setSubject(subject);
      msgHelper.setText(body, true);

      if (attachments != null) {
         String filename = null;
         for (File attachment : attachments) {
            filename = attachment.getName();
            FileSystemResource res = new FileSystemResource(attachment);
            msgHelper.addAttachment(filename, res);
         }
      }

      mailSender.send(message);
   }

   /**
    * Return a list of strings
    * 
    * @param csvList a string containing a comma separated values 
    * @return a list of strings
    */
   public String[] getRecipients(String csvList) {
      String[] values = null;
      if (csvList != null) {
         values = csvList.split(",");
         for (int i = 0; i < values.length; i++)
            values[i] = values[i].trim();
      }
      return values;
   }
}
The pom file you need:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.noushin.spring</groupId>
    <artifactId>email</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>email</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.0.3.RELEASE</spring.version>
        <java.mail>1.4.7</java.mail>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>${java.mail}</version>
        </dependency>

    </dependencies>

</project>

And application context:
<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        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">

    <context:property-placeholder location="file:/home/nbashir/email.properties" />
    
    <!-- Activate annotation configured components -->
    <context:annotation-config />

    <!-- Scan components for annotations within the configured package -->
    <context:component-scan base-package="com.noushin.spring.email" />
        
    <!-- Email handler -->
    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="host" value="${email.host}" />
        <property name="port" value="${email.port}" />
    </bean>

</beans>

Wednesday, April 23, 2014

Spring & Hive

Getting Spring & Hive integration working wasn't a breeze, but I got it. Here is what I had to do:

First, a typical BookRepository class:
package com.noushin.spring.ht.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.hadoop.hive.HiveTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * This class handles accessing books in Hadoop using Hive.
 * 
 * @author nbashir
 * 
 */
@Repository
public class BookRepositroy {

   @Autowired
   private HiveTemplate hiveTemplate;

   public void showTables() {
      List<String> tables = hiveTemplate.query("show tables;");
      System.out.println("tables size: " + tables.size());
   }

   public Long count() {
      return hiveTemplate.queryForLong("select count(*) from books;");
   }
}
Next a typical Service layer class:
package com.noushin.spring.ht.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.noushin.spring.ht.dao.BookRepositroy;

/**
 * This class handles any business logic related to handling books.
 * 
 * @author nbashir
 *
 */
@Component
public class BookService {

   @Autowired 
   BookRepositroy bookRepo;
   
   public Long count() {
      return bookRepo.count();
   }

   public void showTables() {
      bookRepo.showTables();
   }
 }

Here is the pom file you need:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.noushin.spring</groupId>
    <artifactId>ht</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>ht</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.hadoop.version>1.0.2.RELEASE</spring.hadoop.version>
        <hadoop.version>1.2.1</hadoop.version>
        <hive.version>0.10.0</hive.version>
        <spring.version>4.0.3.RELEASE</spring.version>
    </properties>

    <dependencies>

        <!-- Spring Data -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-hadoop</artifactId>
            <version>${spring.hadoop.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context-support</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-core</artifactId>
            <version>${hadoop.version}</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-builtins</artifactId>
            <version>${hive.version}</version>
            <scope>runtime</scope>
        </dependency>
        
    </dependencies>
    
</project>

You application-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:hdp="http://www.springframework.org/schema/hadoop" xmlns:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="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/hadoop http://www.springframework.org/schema/hadoop/spring-hadoop.xsd">

    <context:property-placeholder location="hive.properties" />

    <!-- Activate annotation configured components -->
    <context:annotation-config />

    <!-- Scan components for annotations within the configured package -->
    <context:component-scan base-package="com.noushin.spring.ht" />

    <hdp:hive-client-factory id="hiveClientFactory"
        host="${hive.host}" port="${hive.port}">
        <hdp:script>
            ADD JARS /usr/lib/hive/lib/books.jar;
        </hdp:script>
    </hdp:hive-client-factory>

    <hdp:hive-template id="hiveTemplate" />

</beans>


Your hive.properties:
hive.host=your-hive-server
hive.port=10000
hive.url=jdbc:hive://${hive.host}:${hive.port}/default

And finally a main class to start and run your app:
package com.noushin.spring.ht;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.noushin.spring.ht.service.BookService;

/**
 * Main class to demonstrate accessing MongoDB with Spring Data and MongoTemplate.
 * 
 * @author nbashir
 *
 */
public class HadoopMain {

   public static void main(String[] args) {
      try {
         ApplicationContext ctx = new ClassPathXmlApplicationContext("application-context.xml");
         if (ctx != null) {
            BookService service = ctx.getBean(BookService.class);
            service.showTables();
            Long count = service.count();
            System.out.println("result  : " + count);        
         }
      }
      catch (Exception ex) {
         System.out.println("HadoopMain encountered an error and ended.");
      }
   }
}

Saturday, April 12, 2014

Scheduling a task in Java

Using Spring, scheduling a task is quite simple. Just follow these steps:

1. Write a class that defines the scheduled tasks. Use @Scheduled annotation.
package com.noushin.spring.scheduler;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class TaskScheduler {

   // run the task every n seconds, 5 secs = 5000
   @Scheduled(fixedDelayString = "${task.execution.time.delayed}")
   public void delayedTask() {
      System.out.println("Do something meaningful after each delayed period.");
   }

   // run the task every once in a while, example: 0 13 30 * * * means run this task every day at 1:30 pm
   @Scheduled(cron = "${task.execution.time.every.day}")
   public void dailyTask() {
      System.out.println("Do something meaningful once a day.");
   }

}
2. Write a main class to load Spring's application context.
package com.noushin.spring.scheduler;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SechedulerMain {
   
   static TaskScheduler reportScheduler;
   
   public static void main(String[] args) {
      try {
         ApplicationContext ctx = new ClassPathXmlApplicationContext("application-context.xml");
         if (ctx != null) {
            reportScheduler = ctx.getBean(TaskScheduler.class);
            while (true) {
               System.out.println("main: --------------------------");
               Thread.sleep(1000);
            }          
         }
      }
      catch (Exception ex) {
         System.out.println("SchedulerMain encountered an error and ended.");
         ex.printStackTrace();
      }
   }
}
3. Add application-context.xml.
<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="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/task http://www.springframework.org/schema/task/spring-task.xsd">

 <!-- Scan components for annotations within the configured package -->
 <context:component-scan base-package="com.noushin.spring" />
 
 <context:property-placeholder location="task.properties" />
       
 <!-- Activate annotation configured components -->
 <context:annotation-config />
 
 <!-- Scheduling tasks using annotations -->
 <task:annotation-driven />

</beans>
4. A property file to configure the scheduler, lets call it task.properties.
# Scheduling report job
task.execution.time.delayed=5000
report.execution.time.every.day=13 30 * * * *

Note: Use the Crontab Patterns as defined in : http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html

5. Use the following dependencies in your pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.noushin.spring</groupId>
    <artifactId>scheduler</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>scheduler</name>
    <description>Demo</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <log4j.version>1.2.17</log4j.version>
        <spring.version>4.0.2.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!-- Logging -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <!-- Spring Context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</project>

Monday, February 24, 2014

Spring & MongoTemplate

To keep up with Spring templates theme, I will show you how to use MongoTemplate to access MongoDB. Assuming you are already familiar with MongoDB and the fact that it's a document centric datastore, the first thing we should do is define objects representing documents. In this tutorial, my application will manage books in a MongoDB database. Here is the definition of a book stored as a document.
package com.noushin.spring.monspr.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

/**
 * This class represents a book as a MongoDB document.
 * 
 * @author nbashir
 * 
 */
@Document
public class Book {

   @Id
   private String id;

   @Indexed
   private String name;

   private String author;

   public Book(String id, String name, String author) {
      super();
      this.id = id;
      this.name = name;
      this.author = author;
   }

   public String getId() {
      return id;
   }

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

   public String getName() {
      return name;
   }

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

   public String getAuthor() {
      return author;
   }

   public void setAuthor(String author) {
      this.author = author;
   }
}
Now I need a class to access books in MongoDB. This is where I will utilize MongoTemplate.
package com.noushin.spring.monspr.dao;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Repository;

import com.noushin.spring.monspr.model.Book;

/**
 * This class handles accessing books in MongoDB.
 * 
 * @author nbashir
 *
 */
@Repository
public class BookRepositroy {
   
   @Autowired
   MongoTemplate mongoTemplate;
      
   public void save(Book book) {
      mongoTemplate.save(book);
   }
   
   public void save(List<Book> books) {
      mongoTemplate.save(books);
   }

   public Book get(String id) {
      return mongoTemplate.findById(id, Book.class);
   }
   
   public List<Book> getAll() {
      return mongoTemplate.findAll(Book.class);
   }
   
   public void delete(Book book) {
      mongoTemplate.remove(book);
   }
}
And a typical class to place in the service layer:
package com.noushin.spring.monspr.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.noushin.spring.monspr.dao.BookRepositroy;
import com.noushin.spring.monspr.model.Book;

/**
 * This class handles any business logic related to handling books.
 * 
 * @author nbashir
 *
 */
@Component
public class BookService {

   @Autowired 
   BookRepositroy bookRepo;
   
   public void save(Book book) {
      bookRepo.save(book);
   }
   
   public void save(List<Book> books) {
      bookRepo.save(books);
   }

   public Book get(String id) {
      return bookRepo.get(id);
   }
   
   public List<Book> getAll() {
      return bookRepo.getAll();
   }
   
   public void delete(Book book) {
      bookRepo.delete(book);
   }
}
And last, but not least, a class to load Spring context and do some basic data access operations in regards to our books example:
package com.noushin.spring.monspr;

import java.util.ArrayList;
import java.util.UUID;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.noushin.spring.monspr.model.Book;
import com.noushin.spring.monspr.service.BookService;

/**
 * Main class to demonstrate accessing MongoDB with Spring Data and MongoTemplate.
 * 
 * @author nbashir
 *
 */
public class MongoDbMain {

   final static Logger logger = Logger.getLogger(MongoDbMain.class);

   public static void main(String[] args) {
      try {
         ApplicationContext ctx = new ClassPathXmlApplicationContext("application-context.xml");
         if (ctx != null) {
            logger.info(ctx.getApplicationName() + "MongoDbMain successfuly started. ");
            BookService service = ctx.getBean(BookService.class);
                       
            Book book;
            book = new Book(UUID.randomUUID().toString(), "Ragtime", "E.L. Doctrow");
            service.save(book);
            book = new Book(UUID.randomUUID().toString(), "The March", "E.L. Doctrow");
            service.save(book);
            book = new Book(UUID.randomUUID().toString(), "Andrew's Brain", "E.L. Doctrow");
            service.save(book);
            book = new Book(UUID.randomUUID().toString(), "Wild: From Lost to Found on the Pacific Crest Trail ",
                  "Cheryl Strayed");
            service.save(book);

            ArrayList<Book> books = (ArrayList<Book>) service.getAll();
            for (int i = 0; i < books.size(); i++)
               System.out.println("Book " + i + " : " + books.get(i).getId() + " - " + books.get(i).getName());
            
            for (int i = 0; i < books.size(); i++)
               service.delete(books.get(i));
      
            ArrayList<Book> deltedBooks =  (ArrayList<Book>) service.getAll();
            if (deltedBooks.size() > 0 ) {
               for (int i = 0; i < deltedBooks.size(); i++)
                  System.out.println("Book " + i + " : " + deltedBooks.get(i).getId() + " - " + deltedBooks.get(i).getName());
            }
            else
               System.out.println("All book are successfully removed.");

         }
      }
      catch (Exception ex) {
         logger.error("MongoDbMain encountered an error and ended.", ex);
      }
   }
}
Now that we have the basic Java code in place, we need to configure our app, so it knows how to access the datastore. As with any other Spring application, configuration details are in application-context.xml.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- Activate annotation configured components -->
    <context:annotation-config />

    <!-- Scan components for annotations within the configured package -->
    <context:component-scan base-package="com.noushin.spring.monspr" />

    <!-- Mongo config -->
    <!-- Factory bean that creates the Mongo instance -->

    <bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
        <property name="host" value="[your-mongodb-host]" />
    </bean>

    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongo" ref="mongo" />
        <constructor-arg name="databaseName" value="nbdb" />
    </bean>
</beans>
In the above configuration, my app will be connecting to "nbdb" database, with MongoDB running on a server specified by "host" property of MongoFactoryBean.

To complete this example, here is my pom.xml where application dependecies are listed:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.noushin.spring</groupId>
  <artifactId>monspr</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>monspr</name>
  <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>4.11</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <spring.version>3.2.4.RELEASE</spring.version>
        <spring.data.version>1.3.4.RELEASE</spring.data.version>
    </properties>

    <dependencies>
        <!-- Test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        
        <!-- Logging -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
            
        <!-- Spring Data -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-mongodb</artifactId>
            <version>${spring.data.version}</version>
        </dependency>
        
        <!-- Spring Context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</project>

MongoDB Installation on Linux

To install it on CentOS, run the following commands as root or using sudo.
vi /etc/yum.repos.d/mongodb.repo
Add:
[mongodb]
name=MongoDB Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1
Run:
yum install mongo-10gen mongo-10gen-server
Start mongod as a service:
service mongod start
Stop mongod service:
service mongod stop
View MongoDB log file:
tail -f /var/log/mongo/mongod.log
View MongoDB configuration:
more /etc/mongod.conf
View mongod script:
more /etc/rc.d/init.d/mongod
To access MongoDB admin console:
http://[mongodb-host]:28017
To access MongoDB from the command line, login to the server running it:
mongo
show dbs (list of existing databases)
use [db-name] (ex: use nbdb; if it doesn't exist, create it)
show collections (list of document collections)
db.[collection-name].find() (list the contents of a collection)
exit
On MacOS:

brew update
brew install mongodb
sudo mkdir -p /data/db
sudo mongod

Sunday, February 23, 2014

Spring & JdbcTemplate

In this blog, I will show you how to use Spring JdbcTemplate to access a PostgreSQL database. I am assuming you are already familiar with DAOs, JDBC, Spring, Maven, SQL, and PostgreSQL.

1. Assuming you already have a table in your database to access, create a DAO class. Here is an example:

package com.noushin.spring.db;

import java.util.UUID;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
 * This class handles accessing data in a PostgreSQL database.
 * 
 * @author nbashir
 *
 */
@Repository
public class MyDao {

   private JdbcTemplate jdbcTemplate;

   @Autowired
   public void setDataSource(DataSource dataSource) {
       this.jdbcTemplate = new JdbcTemplate(dataSource);
   }

   public UUID getId() {
      String sql = "SELECT id FROM my_schema.my_table WHERE my_ip_address=inet('10.1.1.1')";
      UUID id = jdbcTemplate.queryForObject(sql, UUID.class);
      return id;
   }
}

2. Create a class to test MyDao.
package com.noushin.spring.db;

import java.util.UUID;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class MyDaoTest {

   @Autowired
   MyDao myDao;
   
   @Test
   public void testGetId() {
      UUID id = myDao.getd();
      System.out.println("Id: " + id);
   }
}
3. Create a test configuration file in ~/workspace/db/src/test/resources/com/noushin/spring/db called MyDaoTest-context.xml.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com.noushin.spring.db" />
    <context:property-placeholder location="jdbc.properties" />
    
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>
</beans>
4. Add jdbc.properties to ~/workspace/db/src/test/resources
jdbc.driverClassName=org.postgresql.Driver
jdbc.url=jdbc:postgresql://my.db.server:my.port/my.db.name
jdbc.username=my.username
jdbc.password=my.password
5. And last but not least, here is your pom file.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.noushin.spring</groupId>
    <artifactId>db</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>db</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <commons-dbcp.version>1.2.2</commons-dbcp.version>
        <junit.version>4.10</junit.version>
        <postgres.version>9.1-901.jdbc4</postgres.version>
        <spring.version>3.2.4.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!-- Test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>org.springframework.test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        <!-- Spring JDBC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>${commons-dbcp.version}</version>
        </dependency>
        <!-- Postgres Driver -->
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>${postgres.version}</version>
        </dependency>
    </dependencies>

</project>
6. Populate your database with some data, and you should be able to run your test case.