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

No comments:

Post a Comment