Dashboard > Documentation > ... > 2. Developer Guide > 2.3. EJB3 Services

View Info

2.3. EJB3 Services

 Documentation Summary
 Page Summary

Introduction

EJB3 technologies come with a very powerful framework for managing and securising enterprise services in an application server (Session Beans) as well as an efficient persistence and query language system (Entity Beans).

Granite Data Services gives you access to EJB3 services via its org.granite.messaging.service.EjbServiceFactory (for Session Beans methods calls) and fully supports Entity Beans serialization back to your Flex application, taking care of lazy loaded associations (both collections and proxies).

Currently, GDS only offers support for the Hibernate implementation of EJB3 entity beans.

For a basic sample with Granite DS and EJB3 working together, download graniteds-ejb3-1.0.0.zip and import it as a new Eclipse project.

Flex Services Configuration

Let's start again with the sample mxml file introduced in the previous section:

Persons.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
    creationComplete="srv.findAllPersons()">

    <mx:RemoteObject id="srv" destination="person" />

    <!-- Display all person's fields in a DataGrid -->
    <mx:DataGrid id="persons" dataProvider="{srv.findAllPersons.lastResult}" />
</mx:Application>

In order to work, this mxml file must be compiled with a services-config.xml file that indicates where to locate the "person" destination and what type of services this destination implements:

services-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<services-config>

    <services>
        <service
            id="granite-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="person">
                <channels>
                    <channel ref="my-graniteamf"/>
                </channels>
                <properties>
                    <factory>ejbFactory</factory>
                </properties>
            </destination>
        </service>
    </services>

    <factories>
        <factory id="ejbFactory" class="org.granite.messaging.service.EjbServiceFactory">
            <properties>
                <lookup>granite.test/{capitalized.destination.id}ServiceBean/local</lookup>
            </properties>
        </factory>
    </factories>

    <channels>
        <channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel">
            <endpoint
                uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"
                class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>

</services-config>

Some explanations, from top to bottom:

<services>...</services>

You may put in this block as many <service ...> nodes as you want. Each of them contains a destination block with an id attribute ("person" in this sample) that may be used in the declaration of a related RemoteObject (see Persons.mxml above). The <channels><channel> child nodes identify a declared channel (basically an http URL where the RemoteObject will connect when retrieving data). The <properties><factory> child nodes identify a declared service factory (an EJB3 factory in this sample): it indicates how Granite DS will find or create your "person" service (here by looking for a session EJB3 in jndi).

<factories>...</factories>

This block declares an EJB3 factory (named "ejbFactory"). <lookup>granite.test/{capitalized.destination.id}ServiceBean/local</lookup> indicates that this factory will lookup in JNDI for a session bean bound to "granite.test/PersonServiceBean/local" (capitalized.destination.id will be replaced by the current destination id "person", after capitalization, ie: "Person"). At this time, you may only use destination.id and capitalized.destination.id variables when specifying the lookup property.

<channels>...</channels>

This block declares a channel-definition named "my-graniteamf" and a endpoint with this uri: http://{server.name}:{server.port}/{context.root}/graniteamf/amf. The server.name and server.port variables will be replaced at runtime by current server connection parameters (ie: IP and port where your Flex app has been retrieved). context.root is resolved at compile time: it is the context path of your webapp (for example: "/test"). Finally graniteamf/amf identifies the mapping of the AMFMessageServlet. Download granite-ejb3-1.0.0.zip and see build.xml (the mxmlc task) for context.root and granite.test.ear/test.war/WEB-INF/web.xml for graniteamf/amf (note: the last "amf" could be anything you want).

Granite DS use Flex 2 standard location for the services-config.xml file: <YOUR_WAR>/WEB-INF/flex/services-config.xml. You may put this file in another location provided that you specify this path in your web.xml. See the sample web.xml file in granite-ejb3-1.0.0.zip.
<service-include> nodes in <services> is not yet supported!

EJB3 (Entity)

Obviously, you also need to write and deploy Entity and Session beans in order to have a meaningful interaction between Flex and your application server. Here is a brief overview of the process (we will restrict ourselves to a simple Entity Bean called "Person" with only a first and a last name):

Person.java
package test.granite.ejb3.entity;

import java.io.Serializable;

import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Version;

@Entity
public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id @GeneratedValue
    private Integer id;

    @Version
    private Integer version;

    @Basic
    private String firstName;

    @Basic
    private String lastName;

    public Integer getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

EJB3 (Session)

Then, we need an interface for a Session bean dealing with Person entity beans:

PersonService.java
package test.granite.ejb3.service;

import java.util.List;
import test.granite.ejb3.entity.Person;

public interface PersonService {
    public List<Person> findAllPersons();
}

We have restricted ourselves to a read only service (persons must be already in the database). The implementation of this interface could be declared as follow:

PersonServiceBean.java
package test.granite.ejb3.service;

import java.util.List;

import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import test.granite.ejb3.entity.Person;

@Stateless
@Local(PersonService.class)
public class PersonServiceBean implements PersonService {

    private static final long serialVersionUID = 1L;

    @PersistenceContext
    private EntityManager manager;

    public List<Person> findAllPersons() {
        Query query = manager.createQuery("select distinct p from Person p");
        return query.getResultList();
    }
}

We have now a Person entity bean managed by a stateless session bean bound by default to [NAME_OF_EAR]/PersonServiceBean/local (provided that we put everything in a "ear" on JBoss).

We will finally need to write a Person.as ActionScript 3 bean in order to replicate Person.java beans in the Flash VM after deserialization (the list of all existing persons must have its ActionScript 3 mirror). See next section on Externalizers for a Person.as implementation.

Packaging all files together in an ear is standard stuff, please refer to JBoss 4.2.* documentation and see a little more sophisticated example in granite-ejb3-1.0.0.zip.


Browse Space
- Pages
- Labels
- Attachments
- Mail
- Bookmarks
- News
- Activity
- Advanced

Explore Confluence
- Popular Labels
- Notation Guide

Your Account
Log In

Other Features

View a printable version of the current page.

Add Content
- Add Comment


Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.6.0 Build:#913 Sep 27, 2007)
Bug/feature request - Contact Administrators

SourceForge.net Logo
Copyright © 2007-2008 Adequate Systems. All Rights Reserved.