11/24/2011

Java Concurrency Quick Guide

A brief overview of the Java Concurrency. Main definitions, liveness issues, high level concurrency objects of the Java Platform, Standard Edition.



View here.

11/21/2011

Tiny Java Mnemonic - Working with Dates, Numbers, and Currency


Here is a brief explanation of how it works.
  • Calendar, DateFormat, NumberFormat are abstract classes, so they should be instantiated via factory methods.
  • [locale], [style] - optional arguments passed to the factory methods.

11/10/2011

Observer Pattern Sample


Observer is a behavioral design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes.

Observer - defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically (the definition from Head First Design Patterns).

Here's a simple Java implementation of this pattern. Also we can extend java.util.Observable class and implement java.util.Observer interface to build observers.

SimpleKeyListener.java:

package observer;

public class SimpleKeyListener implements KeyListener{
    
    public void keyPressed(char key) {
        System.out.println("KeyListener: key pressed..." + key);
    }
    
    public void keyReleased(char key) {
        System.out.println("KeyListener: key released..." + key);
    }
    
    public void keyTyped(char key) {
        System.out.println("KeyListener: key typed..." + key);
    }
    
}

interface KeyListener {
    public void keyPressed(char key);
    public void keyReleased(char key);
    public void keyTyped(char key);
}
package observer;

import java.util.Observable;
import java.util.Observer;

public class SimpleKeyListener implements KeyListener, Observer{
    
    public void keyPressed(char key) {
        System.out.println("KeyListener: key pressed..." + key);
    }
    
    public void keyReleased(char key) {
        System.out.println("KeyListener: key released..." + key);
    }
    
    public void keyTyped(char key) {
        System.out.println("KeyListener: key typed..." + key);
    }

    @Override
    public void update(Observable o, Object obj) {
        if (obj instanceof KeyEvent) {
            KeyEvent keyEvent = (KeyEvent) obj;
            switch (keyEvent.getAction()) {
                case KEY_PRESSED: keyPressed(keyEvent.getCharacter()); break;
                case KEY_RELEASED: keyReleased(keyEvent.getCharacter()); break;
                case KEY_TYPED: keyTyped(keyEvent.getCharacter()); break;
            }
        }
    }
    
}

interface KeyListener {
    public void keyPressed(char key);
    public void keyReleased(char key);
    public void keyTyped(char key);
}

enum KeyEventAction {
    KEY_PRESSED, KEY_RELEASED, KEY_TYPED
}

class KeyEvent {
    
    private KeyEventAction action;
    private char character;
    
    public KeyEvent(KeyEventAction action, char character) {
        super();
        this.action = action;
        this.character = character;
    }
    
    public KeyEventAction getAction() {
        return action;
    }
    
    public char getCharacter() {
        return character;
    }
    
}

Component.java:

package observer;

import java.util.HashSet;
import java.util.Set;

public class Component {
    
    Set<KeyListener> keyListenerList = new HashSet<KeyListener>();
    
    public void addKeyListener(KeyListener keyListener) {
        keyListenerList.add(keyListener);
    }
    public void removeKeyListener(KeyListener keyListener) {
        keyListenerList.remove(keyListener);
    }
    
    
    public void pressKey(char key) {
        // Do work
        System.out.println("Component: pressing key..." + key);
        
        // Send keybords events
        for (KeyListener keyListener : keyListenerList) {
            keyListener.keyPressed(key);
        }
    }
    
    public void releaseKey(char key) {
        // Do work
        System.out.println("Component: releasing key..." + key);
        
        // Send keybords events
        for (KeyListener keyListener : keyListenerList) {
            keyListener.keyReleased(key);
        }
    }
    
    public void typeKey(char key) {
        // Do work
        System.out.println("Component: typing key..." + key);
        
        // Send keybords events
        for (KeyListener keyListener : keyListenerList) {
            keyListener.keyTyped(key);
        }
    }

}
package observer;

import java.util.Observable;

public class Component extends Observable{ 
 
 
 
 
 
   
    public void pressKey(char key) {
        // Do work
        System.out.println("Component: pressing key..." + key);

        // Send keybords events
        setChanged();
        notifyObservers(new KeyEvent(KeyEventAction.KEY_PRESSED, key));

    }
    
    public void releaseKey(char key) {
        // Do work
        System.out.println("Component: releasing key..." + key);
        
        // Send keybords events
        setChanged();
        notifyObservers(new KeyEvent(KeyEventAction.KEY_RELEASED, key));
    }
    
    public void typeKey(char key) {
        // Do work
        System.out.println("Component: typing key..." + key);
        
        // Send keybords events
        setChanged();
        notifyObservers(new KeyEvent(KeyEventAction.KEY_TYPED, key));
    }

}

Main.java:

package observer;

public class Main {

    public static void main(String[] args) {
        Component component = new Component();
        component.addKeyListener(new SimpleKeyListener());
        
        component.pressKey('a');
        component.releaseKey('b');
        
        component.addKeyListener(new SimpleKeyListener());
        
        component.pressKey('c');
        component.releaseKey('d');
        
    }

}
package observer;

public class Main {

    public static void main(String[] args) {
        Component component = new Component();
        component.addObserver(new SimpleKeyListener());
        
        component.pressKey('a');
        component.releaseKey('b');
        
        component.addObserver(new SimpleKeyListener());
        
        component.pressKey('c');
        component.releaseKey('d');
        
    }

}

Output:

Component: pressing key...a
KeyListener: key pressed...a
Component: releasing key...b
KeyListener: key released...b

Component: pressing key...c
KeyListener: key pressed...c
KeyListener: key pressed...c
Component: releasing key...d
KeyListener: key released...d
KeyListener: key released...d
Component: pressing key...a
KeyListener: key pressed...a
Component: releasing key...b
KeyListener: key released...b

Component: pressing key...c
KeyListener: key pressed...c
KeyListener: key pressed...c
Component: releasing key...d
KeyListener: key released...d
KeyListener: key released...d

Examples of using the Observer Pattern

  • Observer Pattern is widely used in Swing based applications. 
  • Another example. Consider that you are programming a stock market application. You'd like to know when the price of a stock changes. Instead of querying the price for each stock, register your observer to a central stock broker then have him notify you every time a price changes.
  • Listener pattern is used in the JVM itself quite a lot. For instance in Java Management Extensions (JMX) you can register asynchronous listeners (named notifications) which JVM will issue whenever some condition is met (like low memory).

11/07/2011

Tiny Java Mnemonic - Backed Collections


These are some methods of TreeSet and TreeMap classes from Java SE 6. They create backed collections which are tied to parent Tree (TreeSet or TreeMap).

Hope it would help someone.

10/18/2011

JBoss Maven Repos

JBoss Maven Repos you can use:
<repository>
            <id>jboss-public-repository-group</id>
            <name>JBoss Public Repository Group</name>
            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
            <layout>default</layout>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </snapshots>
</repository>
<repository>
            <id>jboss-deprecated</id>
            <name>JBoss Deprecated</name>
            <url>https://repository.jboss.org/nexus/content/repositories/deprecated/</url>
            <layout>default</layout>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
</repository>
<repository>
            <id>jboss-maven2-brew</id>
            <name>JBoss Maven 2 Brew Repository</name>
            <url>http://repository.jboss.org/maven2-brew/</url>
            <layout>default</layout>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
</repository>

10/12/2011

Using the JPA2 in Desktop Applications

This post is based upon Database schema described in my previous article.
Here we will try to build a Domain Model for the existent DB.

We will use Maven for project creation and dependencies management, Eclipse IDE for coding, MySQl DB Server for data persistence.

1. Create project in maven


mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart

Define value for property 'groupId' - net.schastny.jpa
Define value for property 'artifactId' - desktop
Define value for property 'version' - 1.0-SNAPSHOT
Define value for property 'package' - net.schastny.jpa


2. Import Project into Eclipse


Import => Existing Maven Projects…


3. Add a plugin into pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>

                <configuration>
                    <mainClass>net.schastny.jpa.App</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

Thus we can run the project.
Eclipse Main Menu => Run => Run Configurations => Maven Build => New Conf:
Base Directory: project dir
Goals: exec:java

4. Update dependencies in pom.xml

<dependencies>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>

    <!-- Hibernate -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>3.3.2.GA</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-annotations</artifactId>
        <version>3.4.0.GA</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>3.3.0.ga</version>
    </dependency>
    
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.5.2</version>
    </dependency>
    
    <!-- MySQL driver -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
    
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>3.3.2.GA</version>
    </dependency>
    
    <!-- JSR 303 Form Validation -->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.0.0.GA</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.1.0.Final</version>
    </dependency>
</dependencies>

5. Add META-INF/persistence.xml

<persistence 
    xmlns="http://java.sun.com/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> 

    <persistence-unit name="company_unit">
        <properties>
            <property name="hibernate.connection.driver_class"     value="com.mysql.jdbc.Driver" />
            <property name="hibernate.connection.url"             value="jdbc:mysql://localhost:3306/company" />
            <property name="hibernate.connection.username"         value="root" />
            <property name="hibernate.connection.password"         value="" />
            <property name="hibernate.dialect"                     value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.show_sql"                 value="true" />
        </properties>
    </persistence-unit>
    
</persistence>

6. Domain Entities

package net.schastny.jpa.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "cats")
public class Category {

    @Id
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @OneToMany(mappedBy = "category")
    private List<Project> projects;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public List<Project> getProjects() {
        return projects;
    }

    public void setProjects(List<Project> projects) {
        this.projects = projects;
    }

}

package net.schastny.jpa.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "projects")
public class Project {

    @Id
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @ManyToOne
    @JoinColumn(name = "cat_id")
    private Category category;

    @ManyToMany(mappedBy = "projects")
    private List<Person> persons;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public List<Person> getPersons() {
        return persons;
    }

    public void setPersons(List<Person> persons) {
        this.persons = persons;
    }

}

package net.schastny.jpa.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "persons")
public class Person {

    @Id
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @ManyToMany
    @JoinTable(
            name = "ptable", 
            joinColumns         = @JoinColumn(name = "person_id", referencedColumnName = "id"), 
            inverseJoinColumns     = @JoinColumn(name = "project_id", referencedColumnName = "id"))
    private List<Project> projects;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public List<Project> getProjects() {
        return projects;
    }

    public void setProjects(List<Project> projects) {
        this.projects = projects;
    }

}

7. DAO Objects

package net.schastny.jpa.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import net.schastny.jpa.domain.Category;

public class CategoryDAO {
 private EntityManagerFactory entityManagerFactory;

 public CategoryDAO() {
  entityManagerFactory = Persistence.createEntityManagerFactory("company_unit");
 }
 
 public void store(Category category) {
  EntityManager manager = entityManagerFactory.createEntityManager();
  EntityTransaction tx = manager.getTransaction();
  try {
   tx.begin();
   manager.merge(category);
   tx.commit();
  } catch (RuntimeException e) {
   tx.rollback();
   throw e;
  } finally {
   manager.close();
  }
 }

 public void delete(Long categoryId) {
  EntityManager manager = entityManagerFactory.createEntityManager();
  EntityTransaction tx = manager.getTransaction();
  try {
   tx.begin();
   Category category = manager.find(Category.class, categoryId);
   manager.remove(category);
   tx.commit();
  } catch (RuntimeException e) {
   tx.rollback();
   throw e;
  } finally {
   manager.close();
  }
 }

 public Category findById(Long categoryId) {
  EntityManager manager = entityManagerFactory.createEntityManager();
  try {
   return manager.find(Category.class, categoryId);
  } finally {
   manager.close();
  }
 }

 public List<Category> findAll() {
  EntityManager manager = entityManagerFactory.createEntityManager();
  try {
   Query query = manager.createQuery("select category from Category category");
   @SuppressWarnings("unchecked")
   List<Category> items = query.getResultList();
   for (Category item : items) {
    item.getProjects().size();
   }
   
   return items;

  } finally {
   manager.close();
  }
 }
 
}

package net.schastny.jpa.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import net.schastny.jpa.domain.Project;

public class ProjectDAO {
    private EntityManagerFactory entityManagerFactory;

    public ProjectDAO() {
        entityManagerFactory = Persistence.createEntityManagerFactory("company_unit");
    }
    
    public void store(Project project) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        EntityTransaction tx = manager.getTransaction();
        try {
            tx.begin();
            manager.merge(project);
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        } finally {
            manager.close();
        }
    }

    public void delete(Long projectId) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        EntityTransaction tx = manager.getTransaction();
        try {
            tx.begin();
            Project project = manager.find(Project.class, projectId);
            manager.remove(project);
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        } finally {
            manager.close();
        }
    }

    public Project findById(Long projectId) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        try {
            return manager.find(Project.class, projectId);
        } finally {
            manager.close();
        }
    }

    public List<Project> findAll() {
        EntityManager manager = entityManagerFactory.createEntityManager();
        try {
            Query query = manager.createQuery("select project from Project project");
            @SuppressWarnings("unchecked")
            List<Project> items = query.getResultList();
            for (Project item : items) {
                item.getPersons().size();
            }
            
            return items;

        } finally {
            manager.close();
        }
    }
    
}

package net.schastny.jpa.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import net.schastny.jpa.domain.Person;

public class PersonDAO {
    private EntityManagerFactory entityManagerFactory;

    public PersonDAO() {
        entityManagerFactory = Persistence.createEntityManagerFactory("company_unit");
    }
    
    public void store(Person person) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        EntityTransaction tx = manager.getTransaction();
        try {
            tx.begin();
            manager.merge(person);
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        } finally {
            manager.close();
        }
    }

    public void delete(Long personId) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        EntityTransaction tx = manager.getTransaction();
        try {
            tx.begin();
            Person person = manager.find(Person.class, personId);
            manager.remove(person);
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        } finally {
            manager.close();
        }
    }

    public Person findById(Long personId) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        try {
            return manager.find(Person.class, personId);
        } finally {
            manager.close();
        }
    }

    public List<Person> findAll() {
        EntityManager manager = entityManagerFactory.createEntityManager();
        try {
            Query query = manager.createQuery("select person from Person person");
            @SuppressWarnings("unchecked")
            List<Person> items = query.getResultList();
            for (Person item : items) {
                item.getProjects().size();
            }
            
            return items;

        } finally {
            manager.close();
        }
    }
    
}

8. Trying the Application

package net.schastny.jpa;

import java.util.List;

import net.schastny.jpa.dao.CategoryDAO;
import net.schastny.jpa.dao.PersonDAO;
import net.schastny.jpa.dao.ProjectDAO;
import net.schastny.jpa.domain.Category;
import net.schastny.jpa.domain.Person;
import net.schastny.jpa.domain.Project;

public class App {

    private CategoryDAO categoryDAO = new CategoryDAO();
    private PersonDAO     personDAO     = new PersonDAO();
    private ProjectDAO     projectDAO     = new ProjectDAO();
    
    private String formatString = "%1$-3s %2$-30s %3$s \n";

    public static void main(String[] args) {
        App app = new App();
        app.printCategoryInfo();
        app.printPersonInfo();
        app.printProjectInfo();
    }
    
    public void printCategoryInfo() {
         List<Category> catList = categoryDAO.findAll();
         System.out.printf(formatString, "Id", "Cat Name", "Projects");
         for (Category category : catList) {
             List<Project> categoryProjects = category.getProjects();
             String categoryProjectsString = " ";
             for (Project project : categoryProjects) {
                 categoryProjectsString += project.getName() + ". ";
             }
             
             System.out.printf(formatString, category.getId(), category.getName(), category.getProjects().size() + categoryProjectsString);
         }
         System.out.print("\n\n\n");
    }
    
    public void printPersonInfo() {
        List<Person> personList = personDAO.findAll();
         System.out.printf(formatString, "Id", "Person", "Projects");
         for (Person person : personList) {
             List<Project> personProjects = person.getProjects();
             String personProjectsString = " ";
             for (Project project : personProjects) {
                 personProjectsString += project.getName() + ". ";
             }
             
             System.out.printf(formatString, person.getId(), person.getName(), person.getProjects().size() + personProjectsString);
         }
         System.out.print("\n\n\n");
    }
    
    public void printProjectInfo() {
        List<Project> projectList = projectDAO.findAll();
         System.out.printf(formatString, "Id", "Project Name", "Persons");
         for (Project project : projectList) {
             List<Person> projectPersons = project.getPersons();
             String projectPersonsString = " ";
             for (Person person : projectPersons) {
                 projectPersonsString += person.getName() + ". ";
             }
             
             System.out.printf(formatString, project.getId(), project.getName(), project.getPersons().size() + projectPersonsString);
         }
         System.out.print("\n\n\n");
    }
}

Remark: Actually many of the actions described above could be done automatically by Eclipse Plugins. For instance there is possibility to create JPA Entities from an existing Database with OEPE JPA Entity Generation Wizard.

Summary

JPA is a standard persistence and object-relational mapping (ORM) framework for Java. It is a part of the EJB 3.0 specification (JSR220).

JPA is provided by the javax.persistence package.

It uses plain-old Java objects to represent items in a relational database.

It is designed to be a persistence framework for Java EE that improves on prior EJB persistence models by addressing their inherent challenges, by being less complex and lighter-weight. 

Further reading: JSR-317 Persistence Specification Final 2.0 Final Release.