dimanche 12 décembre 2010

Some tips for newbies developers on Android 2.2 (like me)

The tips are :
  • Know the devices which are connected
  • Deploy your application on real devices
  • Deploy your application on SD Card
  • Know the location (internal or SD Card) of your application and move it or stop it

jeudi 11 novembre 2010

RESTful client in JavaScript

In the line of my posts regarding consumption of JSON RESTful services in different technologies (JavaFX, Java), I wrote a small client in JavaScript.
As in my previous posts, I use the RESTful service described in RESTful service with JAX-RS (and JPA 2 for the access to the data.

dimanche 10 octobre 2010

RESTful client in Java

Because JavaFX 2.0 will be a Java API, we shall have to use Java (or Groovy, Scala, JRuby,etc ... but this isn't the purpose  of this post) instead of JavaFX Script for use it.
And because, the news UIs creates with JavaFX 2.0 will have to consume RESTtful JSON services, I wrote a small RESTful client in Java.
To do that, I use the JAXB's implementation for JSON from
Jersey and for the RESTful service to be consume, the RESTful service wrote in an old post: RESTful service with JAX-RS (and JPA 2 for the access to the data)

mercredi 1 septembre 2010

Arcade Fire, Html 5, Google Chrome Experiment

It’s not because I’m a big fan of Arcade Fire (Great Show at Rock en Seine, even under the rain) that I speak you of their last "clip", but I think it's a great demo of what we can make with html 5.
The "clip" of: We used to wait
http://www.thewildernessdowntown.com/

dimanche 1 août 2010

RESTful client in JavaFX

In this second part, we are going to create a small application in JavaFX to call the restful service created in the first part.
This small application is the same as the one created in an older post : JavaFX and JPA 2.0 with my custom component, but instead of call directly the database with the help of an entity, we are going to call the restful service.

To create this application, we are going to create :
·         a Music JavaFX Bean as model
·         a client to the RESTFul services (and its JSON parser)
·         an JavaFX User Interface

jeudi 15 juillet 2010

Stephen Chin's Petition to Open Source JavaFX

If you like JavaFX , go to  sign the Stephen Chin’s Petition to Open Source JavaFX !
http://steveonjava.com/javafx-petition/

dimanche 4 juillet 2010

RESTful service with JAX-RS (and JPA 2 for the access to the data)

This is the first part of two, which have for purpose to create a RESTful service with JAX-RS (part 1) and to access it in JavaFX (part 2)
In this first part, we will create a RESTful service using JAX-RS and because this service will have  an access to a database, we will use JPA 2.0.
To do that, we are going:
  • to create the database and one table
  • to create a data source 
  • to create the JPA entity and the persistence.xml
  • and to create the RESTful service which will call the entity

mercredi 16 juin 2010

Slimshady:D5- JavaFX

I don’t know what is Slimshady :D5- JavaFX in comparison with the actual JavaFX, but I think it should be a great technology ! :)
See yourself
http://blogs.sun.com/ant/
And if you have some information about Slimshady:D5, let me know ;)



[Update: October 6, 2010]
I don't know why (may be because of that) , but the Anthony Rogers's blog is down... 
However, you could always see some videos of Slimshady on YouTube you could always see some videos of Slimshady on YouTube

mercredi 26 mai 2010

Distortion effect

After the simple scrolltexts and scrolltexts with a sinusoidal effect, here is just another old bitmap effect used in the demos written for home computers in the 1980s.



For standalone mode 
If you want to try with a bigger image, you can use the glassfish.jpg image instead of the fc-barcelone-logo.jpg and, for a better effect with a bigger image,  use this lines

var factor = (6 * Math.PI) / imageHeight;
    var v = (Math.sin(j * factor) * 20) + 20;
instead of this lines
var factor = (2 * Math.PI) / imageHeight;
    var v = (Math.sin(j * factor) * 10) + 20;
Distortion.fx
package distortion;

import javafx.scene.image.Image;
import javafx.geometry.Rectangle2D;
import javafx.scene.image.ImageView;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.util.Math;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.runtime.ConditionalFeature;
import javafx.runtime.Platform;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.Color;

/**
 * @author paddy
 */
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 img = Image {
            //url: "{__DIR__}images/glassfish.jpg"
            url: "{__DIR__}images/fc-barcelone-logo.jpg"
             }
def imageWidth = bind img.width as Integer;
def imageHeight = bind img.height as Integer;
def lineWidth = imageWidth;
def lineHeight = 1;
var distortionMap: Float[];
var index = 0;

for (j in [0..<imageHeight * 2]) {

    var factor = (2 * Math.PI) / imageHeight;
    var v = (Math.sin(j * factor) * 10) + 20;
    //var factor = (6 * Math.PI) / imageHeight;
    //var v = (Math.sin(j * factor) * 20) + 20;

    insert v into distortionMap;
}

def lineViewports = for (row in [0..imageHeight]) {
            Rectangle2D {
                minX: 0, minY: row, width: lineWidth, height: lineHeight
            }
        }
var distortionImg = bind
        for (row in [0..imageHeight]) {
            ImageView {
                x: bind distortionMap[row + index]
                y:  row
                viewport: bind lineViewports[row]
                image:  img
            }
        }
var t = Timeline {
            repeatCount: Timeline.INDEFINITE
            keyFrames: KeyFrame {
                time: 8ms
                canSkip: true
                action: function (): Void {
                    index = index + 1;
                    if (index > imageHeight) {
                        index = 0;
                    }
                }
            }
        }

t.play();

Stage {
    title: "Application title"
    scene: Scene {
        width: imageWidth +40
        height: imageHeight + 1

        content: [
            Rectangle {
                x: 0, y: 0
                width: imageWidth +40 , height: imageHeight + 1
                fill: Color.BLACK
                //fill: Color.GHOSTWHITE
            }
            distortionImg
        ]
    }
}

Note : The scrolltexts and the scrolltexts with sinusoidal effect work without migration on JavaFX 1.3 with AWT/Java2D/Swing toolkit.
On prism toolkit the animation is very fluid but you have to use a jpeg image instead of png for the font because the png is not supported in this early version of prism

samedi 8 mai 2010

JavaFX custom component in JavaFX 1.3

In JavaFX 1.2, Control extended CustomNode then we could override the create function to customize an existing component.  
With JavaFX 1.3, Control now extends
Parent directly then we do not have any more the create function and my custom component doesn’t compile any more … (because I used the create function to customize my components)

Then, to customize an existing component in JavaFX 1.3, I tried another way


I use the initBlock to create the nodes that I want to add to the existing component to customize it
and then I add these nodes to the children sequence of the existing component.

...
   init {
          var g = Group {
                    content: [
                                Group {
                                    ...
                                    content: [
                                        Circle {
                                               ...
                                        }
                                        Rectangle {
                                               ....
                                        }
                                     ...
                                    ]
                                    ...
                    ]
                }
           insert g into children;
        }
   ...
Now, I have a problem with the css, I want to have a default css for my SearchTextBox which is loaded by default by my component (not in the Scene by the developer) and which can be overridden by the developer.
If you have a solution, please let me know!
This example works on: Windows (Seven), Linux (Ubuntu 10.04) and Mac OS X (10.6.3)  with the Default toolkit and the Prism toolkit (JVM argument: -Xtoolkit prism) but there is one bug when you run it as an applet on Mac OS X.
The button have a wrong size, the text is too long….
[update August 8, 2010]this issue is fixed in JavaFX 1.3.1




SearchTextBox.fx
package customcomponent;

import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.input.MouseEvent;
import javafx.scene.control.TextBox;
import javafx.scene.input.KeyEvent;

/**
 * @author Patrick
 */
public class SearchTextBox extends TextBox {

    public var onResetSearch: function(): Void;
    public var onSearch: function(s: String): Void;

    override var style = "-fx-padding: 0 16 0 0; ";
    //override var styleClass = "searchTextBox text-box";
    //override var styleClass = "searchTextBox";

    override var onKeyTyped = function(event:KeyEvent){
        if (this.rawText!=""){
            onSearch(this.rawText);
        }else{
            onResetSearch();
        }
    }

    init {
          var g = Group {
                    content: [
                                Group {
                                    var crossWidth = bind this.layoutBounds.height * 0.45;
                                    var crossHeight = bind this.layoutBounds.height * 0.05;
                                    visible: bind this.rawText.length() > 0
                                    layoutX: bind this.layoutBounds.width - (this.layoutBounds.height / 2.0)
                                    layoutY: bind this.layoutBounds.height / 2.0
                                    content: [
                                        Circle {
                                            fill: Color.GRAY
                                            radius: bind this.layoutBounds.height * 0.325 // 65% of the texbox height and div 2 for the radius
                                        }
                                        Rectangle {
                                            width: bind crossWidth
                                            height: bind crossHeight
                                            translateX: bind 0 - crossWidth / 2.0
                                            translateY: bind 0 - crossHeight / 2.0
                                            fill: Color.WHITE
                                            rotate: 45
                                        }
                                        Rectangle {
                                            width: bind crossWidth
                                            height: bind crossHeight
                                            translateX: bind 0 - crossWidth / 2.0
                                            translateY: bind 0 - crossHeight / 2.0
                                            fill: Color.WHITE
                                            rotate: -45
                                        }
                                    ]
                                    onMouseClicked: function (event: MouseEvent) {
                                        this.commit();
                                        this.text = "";
                                        onResetSearch();
                                    }
                                }
                    ]
                }           
           insert g into children;
        }
}

Main.fx
package searchtextbox;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.control.Button;
import javafx.scene.control.RadioButton;

import javafx.scene.control.ToggleGroup;
import customcomponent.SearchTextBox;

/**
 * @author Patrick
 */

class ExtRadioButton extends RadioButton {
    public var action:function();

    override public var selected on replace {
        if (selected) {
            action();
        }
    }
}

def macStyleSheet="{__DIR__}resources/mac.css";
def defaultStyleSheet = "/customcomponent/stbcaspian.css";
var stylesheets:String = macStyleSheet;

Stage {
    title: "Application title"
    width: 250
    height: 200

    var cssToggleGroup = ToggleGroup {};

    scene: Scene {
        stylesheets : bind stylesheets
        content: [
            Text {
                font : Font {
                    size : 16
                }
                x: 10
                y: 30
                content: "Search "
            }
            SearchTextBox {
                    styleClass : "searchTextBox"
                    translateX :10
                    translateY :40


                    onResetSearch:function(){
                        println("reset !");
                    }
                    onSearch:function(s: String){
                        println("Search of : {s}");
                    }
            }
            Button {
                    text: "just a button to change focus"
                    translateX :10
                    translateY :80
                    action: function() {
                        println("Hello !")
                   }
            }

            ExtRadioButton {
                            text: "use the default CSS"
                            translateX :10
                            translateY :110
                            toggleGroup: cssToggleGroup

                            action: function() {
                                stylesheets = defaultStyleSheet;
                            }
            }

            ExtRadioButton {
                            text: "use the mac CSS"
                            translateX :10
                            translateY :130
                            toggleGroup: cssToggleGroup
                            selected: true

                            action: function() {
                                stylesheets = macStyleSheet;
                            }
            }
        ]
    }
}

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

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.