Pages

Saturday, April 26, 2008

Flex or Flash JSF Component

For my goal to have Adobe Flex integrated into JSF, I made a jsf component which display flash and flex in a jsf page. This jsf component detects if the flashplayer is installed and if it is the right version, if not then it display a link to install flashplayer.
This is version 1 where I display the flash client in the jsf page. The next version of this jsf component allows flex to interact with the backing beans. I will provide a guide how to achieve this in Flex. This JSF component is like blazeds but then for JSF. If it all works then I shall donates this to the opensource community
This is how it works. First download the jsf component and then add the jar to the taglibs.

Open the jsf page and add xmlns:od to the jsp:root
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0" xmlns:od="http://www.ordina.nl">

Now we can add od:flex jsf component
<od:flex id="first" height="620" width="333" name="dragtree" source="DragTree-debug/DragTree.swf" scriptaccess="sameDomain"/>
Here is an example jsf page where I also use it in a backing bean

<?xml version='1.0' encoding='windows-1252'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:af="http://xmlns.oracle.com/adf/faces"
xmlns:afh="http://xmlns.oracle.com/adf/faces/html"
xmlns:cust="http://xmlns.oracle.com/adf/faces/customizable"
xmlns:od="http://www.ordina.nl">
<jsp:output omit-xml-declaration="true" doctype-root-element="HTML"
doctype-system="http://www.w3.org/TR/html4/loose.dtd"
doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
<jsp:directive.page contentType="text/html;charset=windows-1252"/>
<f:view>
<afh:html>
<afh:head title="flex_jsf">
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1252"/>
</afh:head>
<afh:body>
<h:form>
<af:panelGroup layout="horizontal">
<od:flex id="first"
height="620"
width="333"
name="dragtree"
source="DragTree-debug/DragTree.swf"
scriptaccess="sameDomain"/>

<od:flex id="second" binding="#{flexjsf.binding}"/>

</af:panelGroup>
</h:form>
</afh:body>
</afh:html>
</f:view>
</jsp:root>

Here is the code of the backing bean

package nl.ordina;

import nl.ordina.flex.component.FlexDisplayer;

public class FlexBean {
private FlexDisplayer binding;

public FlexBean() {
}
public void setBinding(FlexDisplayer binding) {
this.binding = binding;
binding.setHeight(500);
binding.setWidth(400);
binding.setName("dragtree");
binding.setScriptaccess("sameDomain");
binding.setSource("DragTree-debug/DragTree.swf");
}
public FlexDisplayer getBinding() {
return binding;
}
}


Please let me know if it works or there is something wrong with it. Good luck. The next version will be more impressive.

Wednesday, April 23, 2008

Get JSF trace and performance info with Faces Trace

On the serverside I saw a great post about Faces Trace with this library you can get trace information and performance information of the jsf page. The trace and performance information can be displayed on the jsf page. Here an example how it looks

You can also see this demo page
In this blog I will show you can use this library in your jsf pages created with jdeveloper.
The first step is to download the jar file and add this to the project libraries.
We also have to make a new taglib entry. Go the project options and go the jsp tag libraries entry and click the add button.

Click user( top of the page ) then new and select the faces trace jar file.

This is how it looks. It uses the ft prefix.
Now we can add a context parameter to the web.xml so we can disable the trace information in production

<context-param>
<param-name>com.prime.facestrace.DISABLE_TRACE</param-name>
<param-value>false</param-value>
</context-param>

The last step is to add faces trace to the jsf page. We add the following line xmlns:ft="http://facestrace.sourceforge.net" to jsp:root element.

<?xml version='1.0' encoding='windows-1252'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:af="http://xmlns.oracle.com/adf/faces"
xmlns:afh="http://xmlns.oracle.com/adf/faces/html"
xmlns:cust="http://xmlns.oracle.com/adf/faces/customizable"
xmlns:ft="http://facestrace.sourceforge.net">
<jsp:output omit-xml-declaration="true" doctype-root-element="HTML"
doctype-system="http://www.w3.org/TR/html4/loose.dtd"
doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>

Add <ft:trace/> under the end tag of the body element

</body>
<ft:trace/>
</html>
</f:view>
</jsp:root>

We are ready to test the jsf page

Saturday, April 19, 2008

Flex and web services using blazeds

I had a request how you can use a web service created with JDeveloper and use it in a flex client. For this I use blazeds (it acts like a proxy), this is not really necessary because you can call the web service from an other domain directly from flex if you use the crossdomain xml.
In this blog I use a normal java class and create with jdeveloper (I use the right mouse button on this class ) a java web service. In the wizard I also check the rest property so I can call this web service as a rest service. This is how the java class looks.

package nl.ordina.ws;

import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
import oracle.webservices.annotations.Deployment;

@WebService(name = "CitiesService")
@Deployment(restSupport = true)
public class Cities {
public Cities() {
}
public List getCities(String countryCode) {
List result = new ArrayList();
if ( countryCode.equalsIgnoreCase("nl") ) {
City c = new City();
c.setCountry("NL");
c.setName("PUTTEN");
result.add(c);
City c2 = new City();
c2.setCountry("NL");
c2.setName("AMSTERDAM");
result.add(c2);
} else if ( countryCode.equalsIgnoreCase("de") ) {
City c = new City();
c.setCountry("DE");
c.setName("BERLIN");
result.add(c);
City c2 = new City();
c2.setCountry("DE");
c2.setName("FRANKFURT");
result.add(c2);
} else {
City c = new City();
c.setCountry(countryCode);
c.setName("NOT FOUND");
result.add(c);
}
return result;
}
}

It has a method getCities with one parameter countryCode and it returns arraylist with cities.
I can run the rest webservice by /CitiesServiceSoapHttpPort/getCities?countryCode=nl
with the following result

<ns0:getCitiesResponse xmlns:ns0="http://ws.ordina.nl/">
<ns0:return xsi:type="ns1:arrayList" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns1:item xsi:type="ns0:City" xmlns:ns1="http://www.oracle.com/webservices/internal/literal">
<ns0:country>NL</ns0:country>
<ns0:name>PUTTEN</ns0:name>
</ns1:item>
<ns1:item xsi:type="ns0:City" xmlns:ns1="http://www.oracle.com/webservices/internal/literal">
<ns0:country>NL</ns0:country>
<ns0:name>AMSTERDAM</ns0:name>
</ns1:item>
</ns0:return>
</ns0:getCitiesResponse>

This is the web service call

<soap:Body xmlns:ns1="http://ws.ordina.nl/">
<ns1:getCities>
<ns1:countryCode>NL</ns1:countryCode>
</ns1:getCities>
</soap:Body>

result envelope

<env:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns0="http://ws.ordina.nl/"
xmlns:ns1="http://www.oracle.com/webservices/internal/literal">
<env:Body>
<ns0:getCitiesResponse>
<ns0:return
xsi:type="ns1:arrayList">
<ns1:item
xsi:type="ns0:City">
<ns0:country>NL</ns0:country>
<ns0:name>PUTTEN</ns0:name>
</ns1:item>
<ns1:item
xsi:type="ns0:City">
<ns0:country>NL</ns0:country>
<ns0:name>AMSTERDAM</ns0:name>
</ns1:item>
</ns0:return>
</ns0:getCitiesResponse>
</env:Body>
</env:Envelope>

Now we know how the result look like, this is important for displaying the result in Flex
Let's look at the flex configuration xml, First the services-config.xml which import the proxy-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service-include file-path="proxy-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>
<channel-definition id="my-http" class="mx.messaging.channels.HTTPChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/http" class="flex.messaging.endpoints.HTTPEndpoint"/>
</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>

The proxy-config.xml has two definitions one for the rest service and one for the web service.

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

<properties>
<connection-manager>
<max-total-connections>100</max-total-connections>
<default-max-connections-per-host>2</default-max-connections-per-host>
</connection-manager>
<allow-lax-ssl>true</allow-lax-ssl>
</properties>

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

<adapters>
<adapter-definition id="http-proxy" class="flex.messaging.services.http.HTTPProxyAdapter" default="true"/>
<adapter-definition id="soap-proxy" class="flex.messaging.services.http.SOAPProxyAdapter"/>
</adapters>

<destination id="ws-rest-cities">
<properties>
<url>http://{server.name}:{server.port}/flex_ws-ws-context-root/CitiesServiceSoapHttpPort/getCities?</url>
</properties>
</destination>
<destination id="ws-cities">
<properties>
<wsdl>http://{server.name}:{server.port}/flex_ws-ws-context-root/CitiesServiceSoapHttpPort?WSDL</wsdl>
<soap>*</soap>
</properties>
<adapter ref="soap-proxy"/>
</destination>
</service>

We are ready for flex application, make sure you select the j2ee server.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#FFFFFF">

<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;

[Bindable]
private var items:ArrayCollection;

private function resultHandler(event:ResultEvent):void {
if ( event.result != null ) {
// ws
items= event.result.item;
// this is for the rest service
if ( items == null ) {
items= event.result.getCitiesResponse['return'].item;
}
grid1.dataProvider=items;
}
}
]]>
</mx:Script>

<mx:HTTPService id="ws_rest"
destination="ws-rest-cities"
result="resultHandler(event)"
useProxy="true"
showBusyCursor="true">
<mx:request>
<countryCode>{country.selectedItem.data}</countryCode>
</mx:request>
</mx:HTTPService>


<mx:WebService id="ws"
destination="ws-cities"
result="resultHandler(event)"
useProxy="true"
showBusyCursor="true">
<mx:operation name="getCities">
<mx:request>
<countryCode>{country.selectedItem.data}</countryCode>
</mx:request>
</mx:operation>
</mx:WebService>

<mx:Form label="Search geonames" id="form" width="332">
<mx:FormItem label="Country">
<mx:ComboBox id="country" width="150">
<mx:dataProvider>
<mx:ArrayCollection>
<mx:source>
<mx:Object label="Netherlands" data="NL"/>
<mx:Object label="Germany" data="DE"/>
</mx:source>
</mx:ArrayCollection>
</mx:dataProvider>
</mx:ComboBox>
</mx:FormItem>
<mx:Button label="Get Data with WS Rest" click="ws_rest.send()"/>
<mx:Button label="Get Data with WS" click="ws.getCities()"/>
</mx:Form>

<mx:DataGrid id="grid1" width="337" height="175">
<mx:columns>
<mx:DataGridColumn dataField="country" headerText="country"/>
<mx:DataGridColumn dataField="name" headerText="city"/>
</mx:columns>
</mx:DataGrid>


</mx:Application>

I use for the rest web service mx:HTTPService and mx:request to add the parameter countryCode and for the web service I use mx:WebService with the mx:operation getCities and use mx:request to add the parameter countryCode. To handle the result I made resultHandler in actionscript.
This how the flex app looks like.

Here is the jdeveloper and flex example code