jeudi 15 avril 2010

EJB 3.1 Asynchronous Session Beans


Before EJB 3.1, if you want to execute an asynchronous processing you had to use JMS and a MDB, not so easy and rather heavy in most cases.
Now with EJB 3.1, you can use a simple session EJB with the @Asynchronous annotation on the method which must be called asynchronously.
@Stateless
@Remote(HelloEjbAsynchronousRemote.class)
public class HelloEjbAsynchronous implements HelloEjbAsynchronousRemote {

    @Asynchronous
    @Override
    public Future<String> ejbAsynchronousSayHello(String name){
If your method has a return value, your method has to return an AsyncResult object which is an implementation of Future.
return new AsyncResult<String>("Hello "+name);
For the client, you just have to call the remote ejbAsynchronousSayHello by using the new portable global JNDI names.
The EJB container returns the control to the client immediately, in my case with a Future object in return, and then executes the method.
HelloEjbAsynchronousRemote ha = 
            (HelloEjbAsynchronousRemote)ic.lookup("java:global/EjbAsynchronous/HelloEjbAsynchronous");
            Future future = ha.ejbAsynchronousSayHello("Patrick");
The client can retrieve the result value with Future.get() and can get the state of the processing with Future.isDone().
String ret = (String)future.get();

Full source code of the EJB - HelloEjbAsynchronous.java
package fr.paddy.ejb31;

import java.util.Date;
import java.util.concurrent.Future;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Remote;
import javax.ejb.Stateless;

@Stateless
@Remote(HelloEjbAsynchronousRemote.class)
public class HelloEjbAsynchronous implements HelloEjbAsynchronousRemote {

    @Asynchronous
    @Override
    public Future<String> ejbAsynchronousSayHello(String name){
        System.out.println(new Date().toString()+" - Begin - HelloEjbAsynchronos->ejbAsynchronousSayHello "+name);

        try{
           Thread.sleep(5*1000);
        }catch (Exception e){
            e.printStackTrace();
        }

        System.out.println(new Date().toString()+" - End - HelloEjbAsynchronos->ejbAsynchronousSayHello "+name);

        return new AsyncResult<String>("Hello "+name);
        
    }
}
The ejbAsynchronousSayHello method, which is declared asynchronous, just wait 5 seconds to simulate a long processing and return the String   "Hello "+name, the variable name being passed as parameter.

Full source code of the remote interface - HelloEjbAsynchronousRemote.java
package fr.paddy.ejb31;

import java.util.concurrent.Future;

public interface HelloEjbAsynchronousRemote {    
    public Future<String> ejbAsynchronousSayHello(String name);
}


Full source code of the EJB Client - ClientMain.java
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import fr.paddy.ejb31.HelloEjbAsynchronousRemote;
import java.util.Date;

public class ClientMain {

    public static void main(String[] args) {
        Properties props = new Properties();
        props.setProperty("java.naming.factory.initial",
                             "com.sun.enterprise.naming.SerialInitContextFactory");
        props.setProperty("java.naming.factory.url.pkgs",
                             "com.sun.enterprise.naming");
        props.setProperty("java.naming.factory.state",
                             "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
        props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
        props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");

        try{
            InitialContext ic = new InitialContext(props);
            String ret="";

            HelloEjbAsynchronousRemote ha =
            (HelloEjbAsynchronousRemote)ic.lookup("java:global/EjbAsynchronous/HelloEjbAsynchronous");
            Future future = ha.ejbAsynchronousSayHello("Patrick");

            while (!future.isDone()){
                Thread.sleep(1000);
                System.out.println(new Date().toString()+" - I do other things ...");
            }

            ret = (String)future.get();
            System.out.println(new Date().toString()+" - ret : "+ret);

        }catch (NamingException ne){
            ne.printStackTrace();
        }catch (InterruptedException ie){
            ie.printStackTrace();
        }catch (ExecutionException ee){
            ee.printStackTrace();
        }
    }
}

Get the Netbeans projects:  EJB , Client
Because of this issue, you must use GlassFish V3.0.1 promoted build 12 to test this example.
Or used this workaround
while (!future.isDone()){
                Thread.sleep(1000);
                System.out.println(new Date().toString()+" - I do other things ...");
                // System.out.println("futur.isDone"+future.isDone());
                // just a hack, because at the moment future.isDone doesn't work !
                try{
                    Object o = future.get(10,TimeUnit.MILLISECONDS);
                }catch (TimeoutException te){
                   // te.printStackTrace();
                }
                // end of the hack
                // System.out.println("futur.isDone"+future.isDone());
            }

jeudi 1 avril 2010

Some examples of the criteria API (JPA 2.0)

When I wrote my examples on how to use JavaFX and JPA 2.0 (part II and III), I made some other tries using Criteria API.
Of course, these examples use the table and the entity described in "Examples using JPA 2.0"
Example using like and a JPA parameter

In JPQL
String param = "Arc%";

        Query query = em.createQuery(
             "select m from Music m where m.artisteName like :param");
        query.setParameter("param", param);
        List<Music> musics = query.getResultList();

        for (Music music : musics){
            System.out.println(music);
        }

Equivalent with Criteria API
String param = "Arc%";

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Music> query = cb.createQuery(Music.class);

        Root<Music> music3 = query.from(Music.class);
        query.where(cb.like(music3.<String>get("artisteName"),
                            cb.parameter(String.class, "param")));

        TypedQuery<Music> tq = em.createQuery(query);
        tq.setParameter("param", param);
        List<Music> musics = tq.getResultList();

        for (Music music : musics){
            System.out.println(music);
        }

Example of criteria API using count
In JPQL
String param = "Archive";

        Query query = em.createQuery(
             "select count(m) from Music m where m.artisteName = :artisteNameParam");
        query.setParameter("artisteNameParam", param);
        Long count1 = (Long)query.getSingleResult();

        System.out.println("count : "+count1);

Equivalent with Criteria API
String param = "Archive";

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Long> query = cb.createQuery(Long.class);

        Root<Music> music = query.from(Music.class);
        query.select(cb.count(music));
        query.where(cb.equal(music.<String>get("artisteName"),
                             cb.parameter(String.class,"artisteNameParam")));

        TypedQuery<Long> tq = em.createQuery(query);
        tq.setParameter("artisteNameParam", param);

        Long count = tq.getSingleResult();

        System.out.println("count : "+count);

Example of criteria using distinct
In JPQL
String param = "Arc%";

        Query query = em.createQuery(
             "select distinct m.artisteName from Music m where m.artisteName like :param");
        query.setParameter("param", param);
        List<String> artistes= query.getResultList();

        for (String artiste : artistes){
            System.out.println(artiste);
        }

Equivalent with Criteria API
String param = "Arc%";

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<String> query = cb.createQuery(String.class);

        Root<Music> music = query.from(Music.class);
        query.select(music.<String>get("artisteName"));
        query.distinct(true);

        query.where(cb.like(music.<String>get("artisteName"),
                            cb.parameter(String.class, "param")));

        TypedQuery<String> tq = em.createQuery(query);
        tq.setParameter("param", param);

        List<String> artistes = tq.getResultList();


        for (String artiste : artistes){
            System.out.println(artiste);
        }

samedi 20 mars 2010

More UI controls for the next release

I don’t know who is Sungmoon Cho, but according to linkedin he is JavaFX Product Line Manager at Sun Microsystems.
Some time ago, he has opened
Official JavaFX Feedback Forum to ask us what we are suggesting for JavaFX.
My answers were (the number before the item, is my number of vote for this item):

And recently (on Friday 19th), Sungmoon Cho updated the the JavaFX FeedBack Forum for the following items:
·         Create more native components, like form items, grids and menus.
with the status planned and the comment
"We are adding a lot more UI controls for the next release. Please stay tuned "
·         Quick application
with the status planned and the comment
"We have a dedicated team of people who work on startup performance. We see significant improvement so far, but we know that it should be much faster. We will update you when we have more data "
·         Quick application startup
with the status under review and the comment
"Many people asked this so we are reviewing this item "

lundi 15 mars 2010

JavaFX and JPA 2.0 with my custom component

In this third and last part, we are going to create a small application which dynamically updates the results in the result list when the user types the search word(s) in a text box.
To do that we will re-use the table and the entity created in the part one, the java class MusicServices.java created in the part two and my search text box that I've created some time ago (with a small correction).

Main.fx
package javafxjpa2searchtextbox;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import customcomponent.SearchTextBox;
import javafx.scene.control.ListView;
import paddy.domain.Music;
import paddy.service.MusicServices;

/**
 * @author Patrick
 */

var listMusic;

var seqMusic:Music[];

var musicServices:MusicServices = MusicServices{};

Stage {
    title: "Application title"
    width: 600
    height: 250
    scene: Scene {
        stylesheets : ["{__DIR__}resources/mac.css"]
        content: [
            Text {
                font: Font {
                    size: 16
                }
                x: 10
                y: 30
                content: "Search DB"
            }
            SearchTextBox {
                translateX: 10
                translateY: 40
                onResetSearch: function () {
                    println("reset !");
                        delete seqMusic;
                    }
                onSearch: function (s: String) {
                    println("Search of : {s}");

                    listMusic = musicServices.getArtisteNameBeginingBy(s);
                    delete seqMusic;
                    seqMusic = listMusic.toArray(seqMusic);

                    }
            }
            ListView {
                layoutY: 75
                width: 575
                height: 100
                items: bind seqMusic
            }
        ]
    }
}

The key points:
  • Delete the sequence on the onResetSearch event of the SearchTextBox component
    delete seqMusic;
  • Call the getArtisteNameBeginningBy method, delete the sequence and refill it on the onSearch event  of the SearchTextBox component
    listMusic = musicServices.getArtisteNameBeginningBy(s);
    delete seqMusic;
    seqMusic = listMusic.toArray(seqMusic);

Get the NetBeans project           
Note: don’t forget to create (in NetBeans) a library containing the jar DerbyClient.jar and being called DerbyClient.

mardi 2 mars 2010

JavaFX and the Databases with JPA 2.0

In the first part, we have seen how to access data with JPA. In this second part we are going to see how to get data from database with JPA 2.0 and to display them with JavaFX.


To do that we will re-use the table and the entity created in the part one, and we will create a Java class which contains the code to execute the JPA requests.
Let’s go and create the Java class.
The Java class contains one constructor to create the EntityManager and 2 methods:
findAll():
This method gets all the records from the table and uses the namedQuery findAllAlbum

getArtisteNameBeginningBy(String begining):
This method get all the records from the table where the field artisteName begin by the parameter
"begining"
For this second method, I use criteria API just because I wanted to test it…
Normally in this case, we don’t have to use criteria API because we don’t need to create dynamically a query and the criteria API was created to build dynamically and safely a query (without to concatenate strings to build a jpql request, like in JPA 1.0).
The best way to do that, is to use directly a jpql request like this


Query query = em.createQuery("select m from Music m where m.artisteName like :param");
query.setParameter("param", param);
List<Music> musics = query.getResultList();

Or, if you want, create another namedQuery in the Entity

@NamedQueries({
   @NamedQuery(name = "findAllAlbum", query= "select m from Music m"),
   @NamedQuery(name = "findAllAlbumWhereArtisteLike",query="select m from Music m where m.artisteName like :param")
})

And call it like that

Query  query = em.createNamedQuery("findAllAlbumWhereArtisteLike");
query.setParameter("param", param);
List<Music> musics = query.getResultList();

We will not use this method in this part but in the last part.

MusicServices.java
package paddy.service;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import paddy.domain.Music;

/**
 *
 * @author Patrick
 */
public class MusicServices {

    EntityManagerFactory emf;
    EntityManager em;

    public MusicServices(){
        emf = Persistence.createEntityManagerFactory("MusicAndLight");
        em = emf.createEntityManager();
    }

    public List<Music> findAll(){

        Query  query = em.createNamedQuery("findAllAlbum");
        List<Music> musics = query.getResultList();

        return musics;
    }

    public List<Music> getArtisteNameBeginningBy(String begining){

        String param = begining+"%";

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Music> query = cb.createQuery(Music.class);
        
        Root<Music> music = query.from(Music.class);
        query.where(cb.like(music.<String>get("artisteName"), param));
        List<Music> musics = em.createQuery(query).getResultList();

        return musics;
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            em.close();
            emf.close();
        } finally {
            super.finalize();
        }
    }
}

Now, let’s call this class from javaFX to get the data from the database and to display them in JavaFX

Main.fx
package javafxjpa2basic;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.Button;
import paddy.domain.Music;
import paddy.service.MusicServices;

/**
 * @author Patrick
 */

var listMusic;
var seqMusic:Music[];

var musicServices:MusicServices = MusicServices{};

Stage {
    title: "Application title"
    scene: Scene {
        width: 600
        height: 175
        content: [
            Button {
                text: "Find all the musics"
                action: function() {
                        delete seqMusic;

                        listMusic = musicServices.findAll();
                        seqMusic = listMusic.toArray(seqMusic);                        

                        println("seqMusic: {seqMusic} ");
                }
            }
            ListView {
                layoutY : 50
                 width: 575
                 height : 100
                 items: bind seqMusic
            }
        ]
    }
}
 
The key points :
  •  Creating an instance of the Java class in JavaFX
    var musicServices:MusicServices = MusicServices{};
  • Calling the findAll method
    listMusic = musicServices.findAll();
  • Converting the java list to a JavaFX sequence
    seqMusic = listMusic.toArray(seqMusic);
  • Binding the sequence to the JavaFX GUI List
    items: bind seqMusic
Note: don’t forget to create (in NetBeans) a library containing the jar DerbyClient.jar and being called DerbyClient.

mardi 23 février 2010

JavaFX Composer, the blog!

The JavaFX Composer Team has opened a new blog about…
JavaFX Composer, of course ;)

http://blogs.sun.com/javafxcomposer/

lundi 22 février 2010

Examples using JPA 2.0

This is the first part of 3 that shows you how to get data from database with JPA 2.0 and display them with JavaFX.
In this first part we are going:
  • to create the database and one table
  • to create the entity and the persistence.xml file
  • to use a namedQuery
  • to use criteria query API
Create the database and the table
  • Create a derby database with :
    • Database Name : javafxDB
    • UserName : APP
    • Password : paddy
  • Create the music table and fill it.
Execute this script to create the music table and fill it
The music table has 3 fields: an auto generated id, the name of the artist (artist_name) and the name of the album (album_title) …
And of course, it’s just for an example ;)
The Entity and the persistence unit
  • The Entity which is mapped to music table

Music.java
package paddy.domain;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQuery;

/**
 *
 * @author Patrick
 */
@Entity
@NamedQuery(name = "findAllAlbum", query= "select m from Music m")

public class Music implements Serializable {

    @Id
    @GeneratedValue
    private Long id;
    @Column(name = "artist_name")
    private String artisteName;
    @Column(name = "album_title")
    private String albumTitle;

    public Music() {
    }
    
    ...
    Getter and setter
    ...
    
    @Override
    public String toString(){

        StringBuffer sb = new StringBuffer();
        sb.append("id : ");sb.append(id);sb.append(" ; ");
        sb.append("artisteName : ");sb.append(artisteName);sb.append(" ; ");
        sb.append("albumTitle : ");sb.append(albumTitle);
        sb.append(" \n");

        return sb.toString();
    }

}
Full source here
The entity is just a plain old Java object (pojo) with some annotations.

@Entity:  designate my pojo as an entity so I can use it with JPA services.
@Id: designate the property as the entity's primary key
@GeneratedValue: used with @Id, it defines that this value is generated automatically
@Column: is used, in my example, to mapped the property of the entity with the field of the table
@NamedQuery(name = "findAllAlbum", query= "select m from Music m")  is used  to create pre-defined queries which get all record from music table.
  • The persistence.xml file
META-INF\persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="MusicAndLight" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>paddy.domain.Music</class>
    <properties>
      <property name="eclipselink.target-database" value="DERBY"/>
      <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
      <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/javafxDB"/>
      <property name="javax.persistence.jdbc.user" value="APP"/>
      <property name="javax.persistence.jdbc.password" value="paddy"/>
    </properties>
  </persistence-unit>
</persistence>
The persistence.xml file defined:
    • the persistence unit named MusicAndLight
    • the entity (paddy.domain.Music) managed by the persistence unit
    • and how the persistence unit connects to the database
Execute query by using a namedQuery
namedQuery
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MusicAndLight");
        EntityManager em = emf.createEntityManager();

        //get and create the namedQuery findAllBum
        Query  query = em.createNamedQuery("findAllAlbum");
        //execute the query
        List<Music> musics = query.getResultList();

        for (Music music : musics){
            System.out.println(music);
        }

        em.close();
        emf.close();
    
Execute query by using a criteria API
Criteria Api
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MusicAndLight");
        EntityManager em = emf.createEntityManager();

        String param = "Arc%";

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Music> query2 = cb.createQuery(Music.class);
        //select * from Music
        Root<Music> music2 = query2.from(Music.class);
        //where artisteName like param
        //in my example where artisteName like Arc% (begining by Arc)
        query2.where(cb.like(music2.<String>get("artisteName"), param));
        //execute the query
        List<Music> musics2 = em.createQuery(query2).getResultList();

        for (Music music : musics2){
            System.out.println(music);
        }

        em.close();
        emf.close();
    

Note: don’t forget to create (in NetBeans) a library containing the jar DerbyClient.jar and being called DerbyClient.