mardi 27 avril 2010

Duke Anim in JavaFX 1.3

In JavaFX 1.3 the evaluation of the KeyValues in the Timeline changed. Now, the KeyValues are evaluated once before the Timeline starts (see "Animation: Changed semantics of KeyValue evaluation" in Java FX 1.3 Migration Guide) and thus my Duke Anim doesn’t work in Java FX 1.3 :(.
To correct it, the function Timeline.evaluateKeyValues()  has been added. This function has to be used for re-evaluates all the keyValues when it is called.
Now, let us correct Duke Anim :)
To correct Duke Anim, I have made only 2 changes:
·         I call the function Timeline.evaluateKeyValues()  at the end of the action function of KeyFrame at 1s.
anim.evaluateKeyValues();
·         And I declare the variable anim with his type to be able to call the function Timeline.evaluateKeyValues()  in the action function of the KeyFrame.
public var anim:Timeline = Timeline { …


This Duke Anim's version works on : Windows (Seven), Linux (Ubuntu 9.10) and Mac OS X (10.6.3)  with the Default toolkit and the Prism toolkit (JVM argument: -Xtoolkit prism)

Main.fx
package dukeanim;

import java.util.Random;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.Scene;
import javafx.scene.transform.Translate;
import javafx.runtime.ConditionalFeature;
import javafx.runtime.Platform;
import javafx.stage.Stage;

class DukeAnimModel {
  
    public var imageURL = "{__DIR__}images/duke.png";
  
    public var x = 0;
    public var y = 0;

    var xTarget = 0;
    var yTarget = 0;

    var xTemp = 0;
    var yTemp = 0;

    public var anim:Timeline =
    Timeline {
        autoReverse: false
        keyFrames: [
            KeyFrame {
                time: 0s
                values: [x => xTemp, y => yTemp]

            },
            KeyFrame {
                time: 1s
                values: [x => xTarget tween
                    Interpolator.SPLINE(0,.5,.5,1),y => yTarget tween
                    Interpolator.SPLINE(0,.5,.5,1)]

                action: function(): Void{

                    var generator = new Random();
                    xTarget = (generator.nextFloat() * 240 + 1) as Integer;
                    yTarget = (generator.nextFloat() * 320 + 1) as Integer;
                  
                    xTemp=x;
                    yTemp=y;

                    anim.evaluateKeyValues();
                }
            },
        ]
        repeatCount: Timeline.INDEFINITE
    };
}

println("Effect enabled: {Platform.isSupported(ConditionalFeature.EFFECT)}");
println("Input Method enabled: {Platform.isSupported(ConditionalFeature.INPUT_METHOD)}");
println("Scene 3D enabled: {Platform.isSupported(ConditionalFeature.SCENE3D)}");
println("Shape Clip enabled: {Platform.isSupported(ConditionalFeature.SHAPE_CLIP)}");

var dukeAnimModel = DukeAnimModel {}
dukeAnimModel.anim.play();

Stage {
    title: "Application title"
    width: 240  
    height: 320 
    scene: Scene {
        content: ImageView {
            transforms: Translate {
                x: bind dukeAnimModel.x
                y: bind dukeAnimModel.y
            }
            image: Image {
                url: dukeAnimModel.imageURL
            }
        }
    }
    onClose: function(){
        println("exit");
    }
}

jeudi 22 avril 2010

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);
        }