Pages

Tuesday, March 11, 2008

Flex app which call a remote java object in JDeveloper ( blazeds )

In this blog I will show you how you can create a simple Adobe Flex application which get the data from java objects which runs in the embedded oc4j container. For this I create a simple webapp where I use the blazeds libraries and configuration files. Then I can just start the webapp in the embedded container, open the flash application and see the results.

We have to create in JDeveloper a new application with no project. Then we create in this workspace a new web project. In this web project we copy the libraries of the blazeds.war to the lib folder ( WEB-INF/lib ). Do the same with the flex configuration files ( flex folder) and copy these files to WEB-INF/flex. I only use remoting-config.xml for defining the java objects and the services-config.xml for configuring the type of service and logging.
the web.xml of the web application must look like this. Where the listener and the messagebroker configuration are needed for flex.

<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee">
<display-name>Flex data</display-name>
<description>Flex data</description>

<!-- Http Flex Session attribute and binding listener support -->
<listener>
<listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>

<!-- MessageBroker Servlet -->
<servlet>
<servlet-name>MessageBrokerServlet</servlet-name>
<servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
<init-param>
<param-name>services.configuration.file</param-name>
<param-value>/WEB-INF/flex/services-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>MessageBrokerServlet</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

<session-config>
<session-timeout>35</session-timeout>
</session-config>
<mime-mapping>
<extension>html</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
<mime-mapping>
<extension>txt</extension>
<mime-type>text/plain</mime-type>
</mime-mapping>

</web-app>

Then I created with BC4J a simple method which retrieves the employees of the scott schema and returns it as a List. Too bad I can not use the RowImpl of the employees viewobject. So I had to create a simple object.


public class Employees {
public Employees() {

}

public List getEmployees() {

System.out.println("called employees");
List list = new ArrayList();
final ScottModuleImpl scott = (ScottModuleImpl)Configuration.createRootApplicationModule("nl.ordina.service.Scottmodule", "ScottModuleLocal");
try {
EmpViewImpl emp = scott.getEmpView();
emp.executeQuery();

while (emp.hasNext()) {
EmpViewRowImpl row = (EmpViewRowImpl) emp.next();
Employee empRecord = new Employee();
empRecord.setName(row.getEname());
empRecord.setEmployeeNumber(row.getEmpno().toString());
list.add(empRecord);
}

} finally {
Configuration.releaseRootApplicationModule(scott, false);
}
return list;
}
}
In the WEB-INF/flex/remoting-config.xml we define the remote object name and the scott employees class.

<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
class="flex.messaging.services.RemotingService">

<adapters>
<adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
</adapters>

<default-channels>
<channel ref="my-amf"/>
</default-channels>

<destination id="Employees">
<properties>
<source>nl.ordina.flex.data.Employees</source>
</properties>
<channels>
<channel ref="my-amf"/>
</channels>
</destination>
</service>


In the WEB-INF/flex/services-config.xml I define the remote objects file, the channel definition and the logging.

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

<services>
<service-include file-path="remoting-config.xml" />
<default-channels>
<channel ref="my-amf"/>
</default-channels>
</services>

<channels>
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>false</polling-enabled>
</properties>
</channel-definition>
</channels>

<logging>
<target class="flex.messaging.log.ConsoleTarget" level="Debug">
<properties>
<prefix>[Flex] </prefix>
<includeDate>false</includeDate>
<includeTime>false</includeTime>
<includeLevel>false</includeLevel>
<includeCategory>false</includeCategory>
</properties>
</target>
</logging>
</services-config>

Now we are ready to start with Adobe Flex builder 3. Here we create a new project.

We have to select the application server type. In our case J2EE and check the option Use remote object access service.
Then next step is to define the j2ee server path with the root folder of the webapp. This is in my case public_html folder. In this folder Flex creates a debug and release build folder for the flash binairy. And you have to define the url of the webapp.

The last step is to create the mxml application file. It looks like this

In the mx:RemoteObject we use the destination which we defined in remote-config.xml In mx:DataGrid we define the java method in my case is that getEmployees dataProvider="{srv.getEmployees.lastResult}"
Now we can run the flex application and it looks like this

12 comments:

  1. Hi,

    I always wanted to build flex app that talk with bc4j via blazeds. It was interesting to read your blog on this. Thank you very much.

    I have the following question, you mentioned in your below statement that we can't use VORowImpl mapped as the remote object. Why is that?

    "Then I created with BC4J a simple method which retrieves the employees of the scott schema and returns it as a List. Too bad I can not use the RowImpl of the employees viewobject. So I had to create a simple object."


    Could you please let me know your thoughts on that?

    It feels not natural to create additional java objects mapped to VOs just for the purpose of using blazeds.

    Thank you.

    Regards,
    Arun

    ReplyDelete
  2. Hi, see chapter 7 of the blazeds doc for the details

    Adobe® BlazeDS and Adobe® Flex™ provide functionality for serializing data to and from ActionScript objects on the
    client and Java objects on the server, as well as serializing to and from ActionScript objects on the client and SOAP
    and XML schema types.

    bc4j viewobject impl can't be serialized. that's why

    ReplyDelete
  3. Hi Edwin,

    I have been contemplating building a Flex UI to front a BC model. Your example works good for a display only app, but when we need data editing, etc. wouldn't it get complicated?

    Do you think there is any way to use ADF Data Controls as the remote service? Or perhaps the session bean interface that ADF BC provides?

    - Bijesh

    ReplyDelete
  4. HI Bijesh

    I have flex dnd example , Where I program the updates. of course there are others. The important is it has to serializable.

    Maybe you can make a flex sdo web service handler so you can make a adf bc sdo ws and use blazeds as a proxy.
    The second option is to use in bc4j ejb session bean. This should work and it is serializable.
    I can help you to made some bc4j flex examples. please keep me informed

    ReplyDelete
  5. Hi I followed a presentation of James Ward. He explained we have to build a factory class for bc4j. Then we can use this class in blazeds and flex.

    If you update a field in flex , then this factory does the update in bc4j and blazeds make sure that the other flex clients ( active push) get the updated field value.

    For hibernate and ejb this already working.

    ReplyDelete
  6. Hi Edwin,

    I am using RemoteObject to call one method i.e. getxmlData(). This method returns a xml data as a string. I want to use this xml data as a data provider to datagrid. But it is giving me some error. i.e In each column of my datagrid its showing me a whole xml code.

    Will u please send me some code...

    Thanx in advance :)

    Regards,
    Pradip jadhav

    ReplyDelete
  7. Hi Pradip,

    maybe you can do something with resultFormat option in the remoteoject.

    maybe this will help.

    or a custom resulthandler
    private var youtubeXml:XML;
    private function resultHandler(event:ResultEvent):void {
    youtubeXml = event.result as XML;

    thanks

    ReplyDelete
  8. Hi, How do I pass Value object to java side by using remote object? Can u plz let me know how it is?

    ReplyDelete
  9. Hi,
    I have created a tree in flex.
    I am selecting a node and displaying the text of selected node in next textbox. Its working fine now. But when in change event , I am calling jee app using blaze ds , passing selected text and retrieving some other text from web app and then displaying. But at this time , its been one event behind. Like when select one node , it shows details of previous node. any help ?

    ReplyDelete
  10. Hi,

    It is async communication with the J2EE server, do you wait for the result and then put this on your screen.

    hope this helps

    ReplyDelete
  11. keep up the nice work, and I will be a common company for a actual continued time.This is a absolutely acceptable apprehend for me. Must accept that you are one of the best blogger I accept anytime read. Thanks for announcement this advisory article.

    ReplyDelete
  12. hi edwin
    i'm working on java object and i need to embed/map my javaobject into acton script ...can u help me out of this

    ReplyDelete