Pages

Saturday, May 29, 2010

HTTP binding in Soa Suite 11g PS2

With Patch Set 2 of Soa Suite 11g Oracle added the HTTP Binding to the supported Adapters. This Adapter was already a feature of Soa Suite 10g, so it is great news that is back. So when your HTTP Service returns a XML message then you can use this binding in your composite application. When the HTTP Service has a  JSON response then you can use the Spring Context Component ( With PS2 Spring Context is supported ). Lucas made a great example how you can achieve this.

In this blogpost I will show how you can use this HTTP Binding as a Service or as a Reference Adapter. I start with a Service so I can use this Service later in the Reference Adapter.
Drag the HTTP Binding from the Component Palette to the Service part of the Composite. Use Service as Type and when you want to have this Service, to return a message then you should select Request-Response as Operation Type.
Provide the Request and Response XSD and choose the right element. For the Request Message Schema you can also use the wizard.
Next step is to wire this Service to a component. Choose a BPEL component and use the Define Service Later template.

Make a wire between the Service and the BPEL component.
Open the BPEL component and a Receive and Reply Activity and finish your BPEL. When everything is valid then you can deploy this to the Soa Suite Server.

For this HTTP Binding Service Soa Suite adds two Port types to the WSDL. This means you can also invoke this Service with a SOAP message.
<wsdl:service name="execute">
        <wsdl:port name="Request_Response_pt" binding="tns:Request_Response_ptHttpGET">
            <http:address xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"  location="http://laptopedwin.wh.lan:8001/soa-infra/services/default/HttpBinding/execute"/>
        </wsdl:port>
        <wsdl:port name="Request_Response_pt_soappt" 
binding="tns:Request_Response_pttBinding">
            <soap:address xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
location="http://laptopedwin.wh.lan:8001/soa-infra/services/default/HttpBinding/execute"/>
        </wsdl:port>
    </wsdl:service>

The Best way to test this HTTP Service is to open the endpoint url in a browser
http://laptopedwin.wh.lan:8001/soa-infra/services/default/HttpBinding/execute
This one is better then the tester of the Enterprise manager.
Here you can choose for the normal Invoke ( Soap message ) or use REST POST or GET

Or you can use the HTTP analyzer of JDeveloper, this is a great way to see the raw request and response


The HTTP binding can also be used as a Reference adapter. For example you can use the just created Service as Endpoint. Provide the Request and Response Schema's.

To test this Reference Adapter you can add a Mediator component with the same Request and Response Schema's. Expose this Mediator as a Service and wire the Reference Adapter to the Mediator and complete the routing rule.
Deploy this composite application, invoke the Mediator Service and take a look at the instances in the Enterprise Manager.

You can download my example at github
https://github.com/biemond/soa11g_examples/tree/master/SoaHTTPBinding
and in here I also have a txt file with all the request I did with the Wfetch tool.


Update by Rakesh


Testing of HTTP Binding adapter works from the browser just fine. It's just that how you pass the parameters.

Here's what I did:
I created a simple composite application with one input parameter and exposed it as REST service using HTTP binding adapter (GET). The service does nothing but add a string to the input parameter and returns back.

The endpoint looks like this:

soatestserver:8001/soa-infra/services/default/TestPatchProject/HTTPBindingService

When you go to test console it forms the test URL string like this

soatestserver:8001/soa-infra/services/default/TestPatchProject/HTTPBindingService/Request-Response?input=Rakesh

All along until now I was trying to use this URL from test console or from the browser.

...but this never works. It's not the right way to use it. If you try this it will return page not found.

What you actually need to use this is below:

soatestserver:8001/soa-infra/services/default/HelloHTTPProject/HTTPBindingService?input=test&operationName=Request-Response

Notice the changes in above URL. The Request-Response is not just after HTTPBindingService (as before), instead its passed as a parameter of operationName.

The above URL works just fine from browser and test console. The auto generated Test URL in test console is misleading.



Tuesday, May 25, 2010

Deploy to Weblogic with Maven

For JDeveloper 11g you can now download a Maven plugin which helps you to make a new project which follows the Maven project folders lay-out and also creates the pom.xml. For more information about this plugin and how it works in JDeveloper see this OTN article of Dana Singleterry.
The next step in this Maven tutorial is to deploy to a Weblogic Server from Maven. To make this work you need to have a Maven Repository, where you can upload the required weblogic jars. In this blogpost I use Artifactory of JFrog. Download the standalone zip and start the Maven repository.
I don't want to upload a lot of Weblogic jars to this repository, so I will generate a Weblogic FullClient jar and use this instead.
Go to the wlserver_10.3\server\lib folder and start java -jar wljarbuilder.jar this will generate a new jar called wlfullclient.jar

Go to the artifactory Web Application, in my case http://localhost:8081/artifactory/webapp/home.html where you need to log in to upload the new jars. Use admin / password as username and password.
In the Deploy Tab you can upload this wlfullclient.jar
Change GroupId & ArtifactId to weblogic and version to 10.3.3
Do the same for the webservices.jar also located in wlserver_10.3\server\lib. Change GroupId to weblogic and version to 10.3.3

When you take a look at the Repository Browser you need to see this.


The next step is to configure the Maven settings.xml Here you need to add a server configuration, a development profile and make this profile active.

The server entry is needed to successful upload your project snapshot to the repository ( distributionManagement in the project pom) and the dev profile is used for the Development Weblogic Server properties and to define the Maven repositories.
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  <servers>
    <server>
       <id>LAPTOPEDWIN</id>
       <username>admin</username>
       <password>password</password>
    </server>
  </servers>

  <profiles>
      <profile>
            <id>dev</id>
            <properties>
                <weblogic.version>10.3.3</weblogic.version>
                <wls.adminServerHostName>laptopedwin</wls.adminServerHostName>
                <wls.adminServerPort>7101</wls.adminServerPort>
                <wls.userId>weblogic</wls.userId>
                <wls.password>weblogic1</wls.password>
            </properties>
            <repositories>
                  <repository>
                        <id>central</id>
                        <url>http://localhost:8081/artifactory/repo</url>
                        <snapshots>
                              <enabled>false</enabled>
                        </snapshots>
                  </repository>
                  <repository>
                        <id>snapshots</id>
                        <url>http://localhost:8081/artifactory/repo</url>
                        <releases>
                              <enabled>false</enabled>
                        </releases>
                  </repository>
            </repositories>
            <pluginRepositories>
                  <pluginRepository>
                        <id>central</id>
                        <url>http://localhost:8081/artifactory/repo</url>
                        <snapshots>
                              <enabled>true</enabled>
                        </snapshots>
                  </pluginRepository>
                  <pluginRepository>
                        <id>snapshots</id>
                        <url>http://localhost:8081/artifactory/repo</url>
                        <releases>
                              <enabled>true</enabled>
                        </releases>
                  </pluginRepository>
             </pluginRepositories>
      </profile>
  </profiles>


  <activeProfiles>
    <activeProfile>dev</activeProfile>
  </activeProfiles>

</settings
The project pom with the weblogic-maven-plugin. This plugin uses the weblogic properties of the dev profile and has the two weblogic jars as dependency. For deploy you need to configure distributionManagement, Maven will upload the snapshot to the artifactory repository.
<?xml version="1.0" encoding="windows-1252" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
        <modelVersion>4.0.0</modelVersion>
        <groupId>nl.whitehorses.maven</groupId>
        <artifactId>test.jpr</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>war</packaging>
        <build>
                <plugins>
                        <plugin>
                                <groupId>org.codehaus.mojo</groupId>
                                <artifactId>weblogic-maven-plugin</artifactId>
                                <version>2.9.1</version>
                                <executions>
                                        <execution>
                                                <phase>deploy</phase>
                                                <goals>
                                                        <goal>deploy</goal>
                                                        <goal>start</goal>
                                                </goals>
                                        </execution>
                                </executions>
                                <configuration>
                                        <name>test</name>
                                        <adminServerHostName>${wls.adminServerHostName}</adminServerHostName>
                                        <adminServerPort>${wls.adminServerPort}</adminServerPort>
                                        <adminServerProtocol>t3</adminServerProtocol>
                                        <userId>${wls.userId}</userId>
                                        <password>${wls.password}</password>
                                        <upload>true</upload>
                                        <remote>true</remote>
                                        <verbose>true</verbose>
                                        <debug>true</debug>
                                        <targetNames>DefaultServer</targetNames>
                                        <noExit>true</noExit>
                                </configuration>
                                <dependencies>
                                        <dependency>
                                                <groupId>weblogic</groupId>
                                                <artifactId>weblogic</artifactId>
                                                <version>10.3.3</version>
                                                <scope>provided</scope>
                                        </dependency>
                                        <dependency>
                                                <groupId>weblogic</groupId>
                                                <artifactId>webservices</artifactId>
                                                <version>10.3.3</version>
                                                <scope>provided</scope>
                                        </dependency>
                                </dependencies>
                        </plugin>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-compiler-plugin</artifactId>
                                <version>2.0.2</version>
                                <configuration>
                                        <source>1.6</source>
                                        <target>1.6</target>
                                </configuration>
                        </plugin>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-war-plugin</artifactId>
                                <version>2.1-alpha-2</version>
                                <configuration>
                                        <webappDirectory>public_html/</webappDirectory>
                                </configuration>
                        </plugin>
                </plugins>
        </build>
        <distributionManagement>
                <repository>
                        <id>LAPTOPEDWIN</id>
                        <name>LAPTOPEDWIN-releases</name>
                        <url>http://localhost:8081/artifactory/ext-releases-local</url>
                </repository>
                <snapshotRepository>
                        <id>LAPTOPEDWIN</id>
                        <name>LAPTOPEDWIN-snapshots</name>
                        <url>http://localhost:8081/artifactory/ext-snapshots-local</url>
                </snapshotRepository>
        </distributionManagement>
</project>
Now you can use mvn deploy and this will deploy your project to the Weblogic Application server. ( when it fails on Windows with a strange Mbean error then this can be caused by, you are using a space in the local repository path ).

Thursday, May 13, 2010

JEJB and EJB3.0 Transport in Oracle Service Bus 11g

With the 11g release of OSB EJB3 is supported in the EJB SB transport. Now you can use all your Remote EJB's of your Model Tier. This is not all, Oracle also added a new Transport called JEJB. This works almost the same, only now you are passing Plain Old Java Objects (POJOs)  through the Service Bus. With the EJB transport the Java Web Services (JWS) framework is used ( easy for transformations ).
With JEBJ you can also use a Java Interface in a Proxy Service and expose this Proxy Service as a Remote EJB. So you can remove the existing EJB and replaced it with this Proxy Service.  Or add some logging or java transformations between the Proxy Service and the original EJB in the Business Service. When you are not using a JEJB Business Service for this Proxy Service then you need to add a java callout in the response and return the right POJO. Soa Suite 11g also has this feature to expose a service as a EJB.

So lets give it a testdrive.

If your remote EJB is running on a different J2EE Server then you need to add a JNDI provider for your EJB  or JEJB Business Services.
Provide the provider Url and the username / password.
Create a service interface jar of your remote EJB. ( This jar must not contain the Bean or the persistence.xml , just the entities and the remote interface ).  Import this jar in your OSB project. Select File system.

Browse to your deploy folder and select the Service interface jar.
EJB Transport
Create a Business Service with a Transport Service Type.
Select the EJB protocol and use this ejb:JNDIModelTier:XXXXXX as an endpoint URI.  JNDIModelTier is the name of the just created JNDI provider and XXXX is the JNDI name of your remote EJB.
In the EJB Transport Tab you need to enable EJB 3, add  the service interface jar and select the remote interface.
You can enable / disable some methods or change the names of the input or output parameters.
Deploy your project to the Service Bus and test the business service in the sbconsole.
Next step is to make a Proxy Service on this Business Service. Generate and save the WSDL on this BS.
You see, there is no XML schema used in the WSDL
Use this WSDL in the proxy service and add in the Service Flow some Operation branches and use the EJB Business Service.
Deploy it and you can also test this in the sbconsole

JEJB Transport
The JEJB Transport works the same, only now, plain java object are transfered. Select JEJB as protocol and as Endpoint URI  jejb:JNDIModelTier:XXXXX  , JNDIModelTier is your JNDI provider and XXXX is the JNDI name of your remote EJB.
Select the EJB 3 option, add the Service Interface jar and select the remote interface.
To test it ,you can make a Proxy Service where you use JEJB as protocol. The Endpoint URI is now JEJBHr_ProxyService. You need this when you try to do a JNDI lookup of this proxy service  like context.lookup("JEJBHr_ProxyService#nl.whitehorses.hr.ejb.services.HrEmployeeEJB")  then a # followed by the remote interface used in this Proxy Service.
Call the JEJB Business Service and Add some Alerts in the request and response. For the request the body contains a nice XML for the response you only get a reference to the POJO. To do something with the response you need to add a java call out.
Make a EJB client and connect to the Oracle Service Bus and lookup the proxy service.
Here is the request alert with a XML presentation of the java call
And the response alert with the java reference
That's all.

Tuesday, May 11, 2010

Using Remote Development Services in Flash Builder 4 and BlazeDS

In Adobe Flex Builder 3 it could be hard to map the data of a remote object or a web service to a FLEX component like a datagrid. With the help of a RDS Servlet in combination with BlazeDS or LifeCycle Data Services you can connect from Flash Builder 4 to your Back End Web Application and generate the required client side code and map this to a Flex component. This also works for a XML file or a Rest Service ( need crossdomain security configured ).

Before you can use it in FB4  you need to download BlazeDS 4 ( Binary Distribution ) and Adobe LifeCycle Data Services ( you only need the flex-rds-lcds.jar ) Add these jars to the WEB-INF/lib folder and provide the BlazeDS configuration files. It will look like this..
 Configure the web.xml with the required RDS and BlazeDS servlets and mappings.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
   id="WebApp_ID" version="2.5">
  <display-name>FlashBuilderWeb</display-name>
    <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>
        <servlet-name>RDSDispatchServlet</servlet-name>
        <servlet-class>flex.rds.server.servlet.FrontEndServlet</servlet-class>
  <init-param>
   <param-name>useAppserverSecurity</param-name>
   <param-value>false</param-value>
  </init-param>        
        <load-on-startup>10</load-on-startup>
    </servlet>

    <servlet-mapping id="RDS_DISPATCH_MAPPING">
        <servlet-name>RDSDispatchServlet</servlet-name>
        <url-pattern>/CFIDE/main/ide.cfm</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
        <servlet-name>MessageBrokerServlet</servlet-name>
        <url-pattern>/messagebroker/*</url-pattern>
    </servlet-mapping>
    
    <listener>
        <listener-class>flex.messaging.HttpFlexSession</listener-class>
    </listener>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
</web-app>

As a demo I created simple  getCities JAX-WS service and added this as a destination in the proxy-config.xml of BlazeDS.
package nl.whitehorses.ws;

import java.util.ArrayList;
import java.util.List;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.WebResult;

@WebService(name   = "CitiesService", 
            serviceName = "CitiesService",
            portName    = "CitiesServicePort")
public class Cities {
    public Cities() {
    }
    
    @WebMethod
    @WebResult(name = "result")
    public List<City> getCities( @WebParam(name = "countryCode" ) String countryCode) {
        List<City> result = new ArrayList<City>();
        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;
    }
}

package nl.whitehorses.ws;

public class City {

    private String name;
    private String country;

    public City() {
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getCountry() {
        return country;
    }
}
Now it is time to do some work in Flash Builder 4. Go to the Data menu and select in this case Connect to Web Service. This works the same for a Remote Object

Select Through a LCDS/BlazeDS proxy destination and select your WS destination. Configured in the proxy-config.xml

Press finish and this will generate the client side code of this WS in your FB4 project.
Go to the Data / Services window and select the getCities WS Operation and press Generate Service Call

This will generate some code in the mxml to call this getCities Operation and handle the result.
Add a datagrid and Bind this to the GetCities Data provider.
Use the Existing call result.
FB4 will now change the DataGrid with the right columns.
That was the hard part and now you can finish this by Adding a Combobox to provide the input for a getCities operation.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
      xmlns:s="library://ns.adobe.com/flex/spark" 
      xmlns:mx="library://ns.adobe.com/flex/mx" 
      xmlns:wscities="services.wscities.*"> 

 <s:applicationComplete>
  <![CDATA[
      initApp();
  ]]>
 </s:applicationComplete>
 
 <fx:Script>
  <![CDATA[
   import mx.controls.Alert;

   public function initApp():void 
   { 
    getCities(country.selectedItem.data);
   } 
   
   protected function getCities(countryCode:String):void
   {
    getCitiesResult.token = wsCities.getCities(countryCode);
   }

   private function changeComboBoxEvt(e:Event):void {
    getCities(e.currentTarget.selectedItem.data);
   }
   
  ]]>
 </fx:Script>

 <fx:Declarations>
  <s:CallResponder id="getCitiesResult"/>
  <wscities:WsCities id="wsCities" fault="Alert.show(event.fault.faultString +
         '\n' + event.fault.faultDetail)" showBusyCursor="true"/>
 </fx:Declarations>

 <s:Panel title="RDC with FB4 &amp; BlazeDS">
  <s:VGroup>
   <mx:ComboBox id="country" width="150" change="changeComboBoxEvt(event)">
    <mx:ArrayList>
     <fx:Object label="Netherlands" data="NL"/>
     <fx:Object label="Germany" data="DE"/>
    </mx:ArrayList>
   </mx:ComboBox>
   
   <mx:DataGrid x="53" y="36" id="dataGrid" dataProvider="{getCitiesResult.lastResult}">
    <mx:columns>
     <mx:DataGridColumn headerText="country" dataField="country"/>
     <mx:DataGridColumn headerText="name" dataField="name"/>
    </mx:columns>
   </mx:DataGrid>
  </s:VGroup>
 </s:Panel>
</s:Application>
If you don't like these mouse clicks you can always do it manually in actionscript.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
      xmlns:s="library://ns.adobe.com/flex/spark" 
      xmlns:mx="library://ns.adobe.com/flex/mx" 
      xmlns:wscities="services.wscities.*"> 

 
 <s:applicationComplete>
  <![CDATA[
  initApp();
  ]]>
 </s:applicationComplete>
 
 <fx:Script>
  <![CDATA[
   import mx.controls.Alert;
   import mx.events.FlexEvent;
   import mx.rpc.AsyncToken;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;
   
   import services.wscities.WsCities;
   
   public var ws:WsCities; 
   
   public function initApp():void 
   { 
    ws = new WsCities(); 
    var token:AsyncToken = ws.getCities(country.selectedItem.data);
    token.addResponder(new mx.rpc.Responder(onCitiesResult, onCitiesFault));
   } 
   
   private function onCitiesResult(e:ResultEvent):void {
    dataGrid.dataProvider=e.result;
   }
   
   private function onCitiesFault(e:FaultEvent):void {
    Alert.show(e.fault.faultString, "Fault");
   }
   
   private function changeComboBoxEvt(e:Event):void {
    var token:AsyncToken = ws.getCities(e.currentTarget.selectedItem.data);
    token.addResponder(new mx.rpc.Responder(onCitiesResult, onCitiesFault));
    
    
   }
  ]]>
 </fx:Script>
 
 <s:Panel title="RDC with FB4 &amp; BlazeDS">
  <s:VGroup>
   <mx:ComboBox id="country" width="150" change="changeComboBoxEvt(event)">
    <mx:ArrayList>
     <fx:Object label="Netherlands" data="NL"/>
     <fx:Object label="Germany" data="DE"/>
    </mx:ArrayList>
   </mx:ComboBox>
   
   <mx:DataGrid x="53" y="36" id="dataGrid" >
    <mx:columns>
     <mx:DataGridColumn headerText="country" dataField="country"/>
     <mx:DataGridColumn headerText="name" dataField="name"/>
    </mx:columns>
   </mx:DataGrid>
  </s:VGroup>
 </s:Panel> 
</s:Application> 

Saturday, May 8, 2010

Setup secure node managers and enable the server migration option

In Weblogic it is not so hard to make a WLS Cluster for your java applications or make a Fusion Middleware cluster for your ADF, Webcenter applications or SOA / OSB processes. But to remotely control this cluster from the console web application you need to setup nodemanagers. If you want to go a little step further and also wants High Availability you need to enable and setup Server Migration in Weblogic. Server Migration only works when you use nodemanagers on all your servers. You can choose for a script nodemager so called SSH nodemanager or for a Java nodemanager.
And the question is, which nodemanager should you choose. 

When you have a normal Weblogic domain ( Don't enable any of the oracle_common options in the Weblogic domain wizard) then you can follow the SSH node manager guide. In this guide you will make a ndmgr account where you copy the weblogic domain from the main domain  location into the home directory of ndmgr account. Enable SSH without password between the weblogic and nodemanager accounts. The Admin Server will fire remote scripts over SSH to control the Managed Servers. There is no agent running only scripts. I think the SSH nodemanager is also possible with a Fusion Middleware Cluster but you can't create or use a ndmgr account and copy the domain to a home directory or to an other path. In Fusion Middleware you can copy the domain to a new folder next to the orginal domain. ( the java jars /ears are loaded on startup with a relative path so in a other path it can't find the ears) and use this domain for your managed servers. So don't use the SSH nodemanager with FMW. For a normal weblogic domain I would choose for SSH , because you can copy domain to the home directory of an account. And the nodemanager does not take any resources.

The first part of this blogpost is about the SSH Nodemanager and the second part is about the Java Nodemanager

Before you can follow these steps you need to install Weblogic ( /oracle/Middleware ) and use oracle as user and group. I will show you the steps for Oracle Enterprise Linux ( RedHat )

SSH Nodemanager
  • Create a user ndmgr which belongs to the oracle group and a home directory /home/ndmgr
  • log on as ndmgr and in the home directory a hidden ssh folder. mkdir.ssh and cd .ssh
  • create a rsa key ssh-keygen -t rsa ( accept the location and use no password )
  • fix the ssh rights by making a keys file copy id_rsa.pub authorized_keys
  • change the permissions of the .ssh folder cd .. and chmod 700 .ssh
  • Log in as root and copy this .ssh folder to all the oracle and ndmgr accounts on all machines
  • Change the owner of this folder chown oracle:oracle .ssh or chown ndmgr:oracle .ssh
  • For Server migration and fire sudo commands over SSH you need to edit  vi /etc/sudoers this allows ifconfig command for the oracle and ndmgr account
  • Add oracle ALL=NOPASSWD: /sbin/ifconfig,/sbin/arping
  • Add ndmgr ALL=NOPASSWD: /sbin/ifconfig,/sbin/arping
  • Enable sudo over ssh by disabling this rule Defaults  requiretty
  • Restart ssh cd /etc/init.d and ./sshd stop and ./sshd start
Log in as oracle and test the ssh  connections to all the servers  ssh -l ndmgr server1_ip_address

Test adding a new ip address with the weblogic script.
cd /oracle/Middleware/wlserver_10.3/common/bin
./wlsifconfig.sh -addif eth0 10.10.10.150 255.255.255.0
./wlsifconfig.sh -removeif eth0 10.10.10.150



The next step is create a Weblogic domain and copy this to ndmgr account.
  • Start the domain wizard cd /oracle/Middleware/wlserver_10.3/common/bin and start ./config.sh
  • Don't enable the oracle_common options
  • log in as root and copy this domain from the user_project folder to the ndmgr home directory like cp -R /oracle/Middleware/user_projects/domains/wls_domain /home/ndmgr
  • Change the rights to the ndmgr user chown ndmgr:oracle /home/ndmgr/wls_domain
  • log in as ndmgr and create in the home directory a new file vi nodemanager.domains
  • Add the local domain path /home/ndmgr/wls_domain
  • Go to the bin folder of your local domain and change in each script the domain variable value to the home directory path.
  • Create a boot.properties file for each managed server because else weblogic will ask for a password and this will not work remotely. cd /home/ndmgr/wls_domain  and  mkdir -p servers/Server_1/security Do this for every server
  • add username=weblogic and password=weblogic
You can test  it when you log in as oracle and try to ask the status of a managed server.
ssh -l ndmgr -o PasswordAuthentication=no  Server_ip_address /oracle/Middleware/wlserver_10.3/common/bin/wlscontrol.sh -d wls_domain -n /home/ndmgr -c -f startManagedWebLogic.sh -s \'Server_1\' STAT

The SSH nodemanager does not have a nodemanager.properties file so you need to change the settings in the oracle/Middleware/wlserver_10.3/common/bin/wlscontrol.sh file. In our case you need to add the network device name and subnet mask.
Interface=${WLS_Interface:-"eth0"}
NetMask=${WLS_NetMask:-"255.255.255.0"}
 

The last part of the SSH node manager is to configure these node manager in the weblogic console.
  • go to http://xxxx:7001/console
  • Environment / Machines  and select the right servers
  • In the Node Manager Tab use the following values
  • Type = SSH 
  • Listen Address=  your server ip address
  • Node manager home = /home/ndmgr
  • Shell Command = ssh -l ndmgr -o PasswordAuthentication=no -p %P %H /oracle/Middleware/wlserver_10.3/common/bin/wlscontrol.sh -d %D -n /home/ndmgr -c -f startManagedWebLogic.sh -s %S %C
for more information see the Oracle Weblogic documentation


Java Nodemanager
For you can configure the nodemanager you need to start the node manager once. This will create the nodemanager.properties file.
  • cd /oracle/Middleware/wlserver_10.3/server/bin
  • ./startNodeManager.sh

Enable sudo for the oracle account
  • For Server migration you need to edit  vi /etc/sudoers this allows ifconfig command for the oracle  account
  • Add oracle ALL=NOPASSWD: /sbin/ifconfig,/sbin/arping
  • Restart ssh cd /etc/init.d and ./sshd stop and ./sshd start

Test adding a new ip address with the weblogic script
cd /oracle/Middleware/wlserver_10.3/common/bin

./wlsifconfig.sh -addif eth0 10.10.10.150 255.255.255.0
./wlsifconfig.sh -removeif eth0 10.10.10.150


For secure communication between your Admin Server and the Java Nodemanamger you need to create some certificates. wls1.local matches with my machine name. Important for hostname verification.
  • java utils.CertGen welcome wls1_cert wls1_key domestic wls1.local
  • java utils.ImportPrivateKey wls1KeyStore.jks welcome wls1 welcome /oracle/Middleware/base_domain/wls1/certs/wls1_cert.pem /oracle/Middleware/base_domain/wls1/certs/wls1_key.pem

Make a new truststore based on the weblogic truststore
  • cp /oracle/Middleware/wlserver_10.3/server/lib/cacerts /oracle/Middleware/base_domain/wls1/certs/wls1TrustKeyStore.jks
  • cd /oracle/Middleware/base_domain/wls1/certs/
  • keytool -storepasswd -new welcome -keystore wls1TrustKeyStore.jks -storepass changeit
  • keytool -import -v -noprompt -trustcacerts -alias clientCACert -file /oracle/Middleware/wlserver_10.3/server/lib/CertGenCA.der -keystore wls1TrustKeyStore.jks -storepass welcome
Configure the nodemanager.properties by adding the network interface / subnet mask and the right certificates
  • cd /oracle/Middleware/wlserver_10.3/common/nodemanager
  • vi nodemanager.properties
  • Add or change these lines 
  • NetMask=255.255.255.0
    Interface=eth0
    StartScriptEnabled=true
    StopScriptEnabled=true
  • Add the security parameters
  • KeyStores=CustomIdentityAndCustomTrust
    CustomIdentityKeyStoreFileName=/oracle/Middleware/base_domain/wls1/certs/wls1KeyStore.jks
    CustomIdentityKeyStorePassPhrase=welcome
    CustomIdentityAlias=wls1
    CustomIdentityPrivateKeyPassPhrase=welcome
you are ready with the nodemanager configuration and can go to the weblogic console application.
  • go to http://xxxx:7001/console
  • go to environment / machines and select the right machine and go the Node manager Tab
  • Change the node manager field
  • Type = SSL
  • Listen Address = your server ip address
  • Listen Port = 5556
Next step is to change the server keystore and ssl properties
  • go to environment / servers and select the right server
  • Go to the Keystores Tab of the configuration Tab and use these values
  • Keystores = Custom Identity and Custom Trust
  • Custom Identity Keystore = /oracle/Middleware/base_domain/wls1/certs/wls1KeyStore.jks
  • Provide the Custom Identiy Keystore Passphrase
  • Custom Trust Keystore = /oracle/Middleware/base_domain/wls1/certs/wls1TrustKeyStore.jks
  • Provide the  Custom Trust Keystore Passphrase
  • go the SSL Tab
  • Private Key Alias = wls1
  • Provide Private Key Passphrase 
That's all for the java node manager

Enable Server migration
To enable server migration you need to have a database with a table called ACTIVE. The scripts for all database are located at /oracle/Middleware/wlserver_10.3/server/db. for HA you can choose Oracle RAC or MySQL Cluster ( the community edition , this is very light and free ).

See this chapter how to configure WLS for this leasing table.

After that you can set a virtual ip address on your managed servers and configure the cluster and managed servers for migration. See this Oracle Chapter

Sunday, May 2, 2010

WSM in FMW 11g Patch Set 2 and OSB 11g

With all the Fusion Middleware releases of late April 2010 its nice to take a look at the security part of FMW & OSB 11g. You may already know FMW 11g Patch Set 2 is a patch on PS1 which was a full release but OSB 11g is a new release. Lets see if Oracle changed WSM in PS2 and what they did with the Weblogic 9.2 WS-Security policies in OSB 11g.
Lets start with WSM  in PS2, I did some checks and came to the conclusion that it works the same as in PS1, so my WSM in FMW blogpost is still valid. The only thing what changed is that JDeveloper 11g PS2 give you more information about the WSM policies.
   
OSB11g is a major release and in this 11g release Oracle did not change the WS-Security policies of  Weblogic 9.2, so my OSB blogpost about the security policies in OSB 10.3 is still valid in the 11g version. From this you can conclude Oracle is going full for WSM. With OSB 11g Oracle added support for WSM agents. You can now use the WSM server policies on your OSB Proxy services and the WSM client policies on the OSB Business services. But more inportant, it is now easy to call these secured WSM proxy services from other FMW components ( ADF , Soa Suite & Java )
To use WSM in OSB 11g you need to have a MDS repository and extend the OSB Domain with the WSM components.
When your OSB server is running then you can add the WSM server policy to a Proxy Service. Just select the OWSM policy option and add the right WSM server policy

It works the same for an OSB business service only now you use the client policies.
Before you can test these WSM policies you need to follow the steps of  my FMW WSM blogpost . If you configured the WSM keystore then you can test the proxy service in the service bus console application ( sbconsole) . In the security part of this testpage you only  need to provide the keystore.recipient.alias. Leave the rest empty.

Or you can generate a web service proxy service in JDeveloper and use this in your Proxy client.
public class HelloWorldServiceSoapHttpPortClient
{
  @WebServiceRef
  private static HelloWorldService_Service helloWorldService_Service;

  public static void main(String [] args)
  {
    helloWorldService_Service = new HelloWorldService_Service();
        SecurityPolicyFeature[] securityFeatures =
            new SecurityPolicyFeature[] { new SecurityPolicyFeature("oracle/wss10_message_protection_client_policy") };
        HelloWorldService helloWorldService = helloWorldService_Service.getHelloWorldServiceSoapHttpPort(securityFeatures);
        // Add your code to call the desired methods.

        Map<String, Object> reqContext = ((BindingProvider) helloWorldService).getRequestContext();
        reqContext.put(ClientConstants.WSSEC_KEYSTORE_TYPE, "JKS");
        reqContext.put(ClientConstants.WSSEC_KEYSTORE_LOCATION, "C:\\test_keystore.jks");
        reqContext.put(ClientConstants.WSSEC_KEYSTORE_PASSWORD, "password");
        reqContext.put(ClientConstants.WSSEC_SIG_KEY_ALIAS, "client_key");
        reqContext.put(ClientConstants.WSSEC_SIG_KEY_PASSWORD, "password");
        reqContext.put(ClientConstants.WSSEC_ENC_KEY_ALIAS, "client_key");
        reqContext.put(ClientConstants.WSSEC_ENC_KEY_PASSWORD, "password");
        reqContext.put(ClientConstants.WSSEC_RECIPIENT_KEY_ALIAS, "client_key");
        

        System.out.println(helloWorldService.sayHello());

  }
}
       

Saturday, May 1, 2010

Lets SOA Suite UMS do your Application Messaging

With User Messaging Service you can let Soa Suite 11g do all your Messaging. And UMS can do a lot: like Email with Attachments, Instant Messaging (XMPP, like Google Talk), SMS Text messages (SMPP), Fax or Voice Messages and deliver messages to the Soa & Webcenter Task List. Besides this, UMS keeps track of delivery status information provided by messaging gateways and makes this information available to applications so that they can respond to a failed delivery.
In Patch Set 2 of Soa Suite 11g Oracle added a simple java API for UMS and in this blogpost I will use this API in a EJB Session Bean with a Remote Interface and also expose this Session Bean as a Web Service. This Session Bean & Web Service can be used in your custom applications so you don't need to have or build your own messaging methods because Soa Suite can do more and much better and even keeps track of your messages. Just call the Web Service or the Session Bean, deliver a list of Receivers with names and the media delivery type and it will return a MessageId with this you can check the status of your send messages.

In this blogpost I will use the email and instant messaging driver to deliver my messages. And as a demo I can send email attachements, deliver a message to IM and Email Client. ( Multi part Message , plain text part for IM and HTML part for Email ) and at last get retrieve the status of these messages. And you can use this in SoapUI, a web service proxy or in a EJB java client.

First you need to enable and configure the UMS Email and Instant Messaging Driver ( XMPP).
Go to the Weblogic console of your Soa Domain probably http://xxxxx:7001/console and select the XMPP UMS driver and go the the target tab and enable the Soa servers or soa cluster.

You need to reboot the Soa Server managed Servers.
In the User Messaging Service part of the Enterprise Manager Website http://xxxx:7001/em you can select the xmpp driver and go the XMPP Driver Properties.
In my case I will use Google Talk as IM service. Provide the server and a Talk user account.
Do the Same for your UMS Email driver. Provide the SMTP server.
And enable all the Work Flow communications in the WorkFlow Notifications Properties page of the Soa Infrastructure part..

You need to reboot the Soa Server managed Servers.

Now you can go to the developer part and create a JDeveloper project and add an new Application. Your project needs to have the UMS library located at jdeveloper\communications\modules\oracle.sdp.messaging_11.1.1\sdpmessaging.jar and your application also needs to have a reference to the oracle.sdp.messaging shared library. Do this in the weblogic-application.xml.
This EJB / WS needs to deployed on the Soa Suite Managed Servers.

To make things more simple I made two entities Receiver and Status.
The Receiver just needs an email address and type ( EMAIL or IM )
package nl.whitehorses.soa.ums.entities;

import java.io.Serializable;

public class Receiver implements Serializable{
    public Receiver() {

    }

    private String receiver;
    private String channel;

    public Receiver(String receiver, String channel) {
        super();
        this.receiver = receiver;
        this.channel = channel;
    }

    public void setReceiver(String receiver) {
        this.receiver = receiver;
    }

    public String getReceiver() {
        return receiver;
    }

    public void setChannel(String channel) {
        this.channel = channel;
    }

    public String getChannel() {
        return channel;
    }
}
The Status entity gives some simple info about the send messages.
package nl.whitehorses.soa.ums.entities;

import java.io.Serializable;
import java.util.Date;

public class Status implements Serializable {
    public Status() {
    }
      
    private String messageId;
    private Date   sendTime;
    private String receiver;
    private String status;

    public Status(String messageId, Date sendTime, String receiver,
                  String status) {
        super();
        this.messageId = messageId;
        this.sendTime = sendTime;
        this.receiver = receiver;
        this.status = status;
    }

    public void setMessageId(String messageId) {
        this.messageId = messageId;
    }

    public String getMessageId() {
        return messageId;
    }

    public void setSendTime(Date sendTime) {
        this.sendTime = sendTime;
    }

    public Date getSendTime() {
        return sendTime;
    }

    public void setReceiver(String receiver) {
        this.receiver = receiver;
    }

    public String getReceiver() {
        return receiver;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getStatus() {
        return status;
    }
    
    public String toString() {
      return "message id: "+ messageId+" time: "+sendTime.toString()+ " status: " +status + " receiver: " + receiver;  
    }
}
Here the main code with three method sendMailAttachmentMsg, sendMixedMsg and getMessageStatus.
The sendMailAttachmentMsg method will only send Mail with Attachments and sendMixedMsg method can send messages to Google Talk and Email, it depends on the receivers and getMessageStatus returns the Statusses of the send messages.
package nl.whitehorses.soa.ums.services;


import javax.ejb.Remote;
import javax.ejb.Stateless;

import java.util.HashMap;
import java.util.Map;

import java.util.ArrayList;
import java.util.List;

import javax.activation.DataHandler;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;

import nl.whitehorses.soa.ums.entities.Receiver;
import nl.whitehorses.soa.ums.utilities.ReceiverConvertor;

import oracle.sdp.messaging.Address;
import oracle.sdp.messaging.ApplicationInfo;
import oracle.sdp.messaging.DeliveryType;
import oracle.sdp.messaging.Message;
import oracle.sdp.messaging.MessagingFactory;
import oracle.sdp.messaging.MessagingClient;
import oracle.sdp.messaging.MessagingClientFactory;
import oracle.sdp.messaging.MessagingException;
import oracle.sdp.messaging.Status;
import oracle.sdp.messaging.util.ByteArrayDataSource;
import oracle.sdp.messaging.util.StringDataSource;

@Stateless(name="SessionEJB", mappedName = "SoaUMSMessaging-SessionEJB")
@Remote
@WebService(name        = "UMSMessagingService", 
            serviceName = "UMSMessagingService",
            portName    = "UMSMessagingServicePort")
public class SessionEJBBean implements SessionEJB {

    MessagingClient mClient = null;
    Map<String, Object> params = new HashMap<String, Object>();

    public SessionEJBBean() {
      params.put(ApplicationInfo.APPLICATION_NAME, "CompanyMsgr");
      params.put(ApplicationInfo.APPLICATION_INSTANCE_NAME, "CompanyInstance");
    }

    @WebMethod
    @WebResult(name = "messageId")
    public String sendMailAttachmentMsg(
                                        @WebParam(name = "sender")    String sender, 
                                        @WebParam(name = "receivers") List<Receiver> receivers,
                                        @WebParam(name = "subject")   String subject,
                                        @WebParam(name = "message")   String message,
                                        @WebParam(name = "data") byte[] data,
                                        @WebParam(name = "mimetype") String mimetype,
                                        @WebParam(name = "filename") String fileName) {

      MimeMultipart mp = null;

      try {
          // plain msg for the body
          MimeBodyPart mp_partPlain = new MimeBodyPart();
          mp_partPlain.setText(message);
        
          // binary attachement
          MimeBodyPart mp_partBinary = new MimeBodyPart();
          ByteArrayDataSource dataSource = new ByteArrayDataSource(data, mimetype);
          mp_partBinary.setDataHandler(new DataHandler(dataSource));
          mp_partBinary.setFileName(fileName);

          mp = new MimeMultipart("alternative");
          mp.addBodyPart(mp_partPlain);
          mp.addBodyPart(mp_partBinary);
      
      } catch (javax.mail.MessagingException e) {
          e.printStackTrace();
      }   

        try {
          Message soaMessage = MessagingFactory.createMessage();
          Address soaSender =
              MessagingFactory.buildAddress(sender, 
                                            DeliveryType.EMAIL,
                                            null);

          soaMessage.setSubject(subject);
          soaMessage.setContent(mp, "multipart/alternative");
          
          soaMessage.addSender(soaSender);
          soaMessage.addAllRecipients(ReceiverConvertor.convertReceiver(receivers));

          mClient = MessagingClientFactory.createMessagingClient(params);
          String messageId = mClient.send(soaMessage);
          return messageId;

        } catch (MessagingException e) {
             e.printStackTrace();
        }
 
        return null;
    }


    @WebMethod
    @WebResult(name = "statusses")    
    public List<nl.whitehorses.soa.ums.entities.Status> getMessageStatus(
            @WebParam(name = "messageId") String messageId) {

        try {
            mClient = MessagingClientFactory.createMessagingClient(params);
            Status[] msgStatuses = mClient.getStatus(messageId);
            List<nl.whitehorses.soa.ums.entities.Status> statusses =
                new ArrayList<nl.whitehorses.soa.ums.entities.Status>();

            for (Status msgStatus : msgStatuses) {
                nl.whitehorses.soa.ums.entities.Status status =
                    new nl.whitehorses.soa.ums.entities.Status();
                status.setMessageId(msgStatus.getMessageId());
                status.setReceiver(msgStatus.getAddress().toString());
                status.setStatus(msgStatus.getType().toString());
                status.setSendTime(msgStatus.getDate().getTime());
                statusses.add(status);
            }
            return statusses;
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return null;
    }

    @WebMethod
    @WebResult(name = "messageId")
    public String sendMixedMsg(@WebParam(name = "subject") String subject,
                               @WebParam(name = "message") String message, 
                               @WebParam(name = "sender") String sender, 
                               @WebParam(name = "receivers") List<Receiver> receivers) {


        Message soaMessage = MessagingFactory.createMessage();
        MimeMultipart part_mp = null;

        try {
          // IM Message  
          MimeBodyPart part_mp_partPlain = new MimeBodyPart();
          // set IM  
          part_mp_partPlain.addHeader(soaMessage.HEADER_SDPM_PAYLOAD_PART_DELIVERY_TYPE,
                                      "IM");
          part_mp_partPlain.setText(message);
 
          // Email Message             
          MimeBodyPart part_mp_partRich = new MimeBodyPart();
          // set Email  
          part_mp_partRich.addHeader(soaMessage.HEADER_SDPM_PAYLOAD_PART_DELIVERY_TYPE,
                                     "EMAIL");
          StringDataSource htmlDataSource = 
              new StringDataSource("<html><head></head><body><b><i>"+
                                   message+ 
                                   "</i></b></body></html>",
                                   "text/html; charset=UTF-8");
          part_mp_partRich.setDataHandler(new DataHandler(htmlDataSource));
    
          part_mp = new MimeMultipart("alternative");
          part_mp.addBodyPart(part_mp_partPlain);
          part_mp.addBodyPart(part_mp_partRich);

        } catch (javax.mail.MessagingException b) {
              b.printStackTrace();
        }


        try {
            mClient = MessagingClientFactory.createMessagingClient(params);

            soaMessage.setSubject(subject);
            soaMessage.setContent(part_mp, "multipart/alternative");
            // Enabled for IM and Email
            soaMessage.setMultiplePayload(true);

            Address soaSender = MessagingFactory.buildAddress(sender,
                                                              DeliveryType.EMAIL,
                                                              null);

            soaMessage.addSender(soaSender);
            soaMessage.addAllRecipients(ReceiverConvertor.convertReceiver(receivers));

            String messageId = mClient.send(soaMessage);
            return messageId;
        } catch (oracle.sdp.messaging.MessagingException b) {
            b.printStackTrace();
        }
        return null;
    }

}

My EJB test client
package nl.whitehorses.soa.ums;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

import java.io.IOException;

import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import java.util.ArrayList;
import java.util.Hashtable;

import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import nl.whitehorses.soa.ums.entities.Receiver;
import nl.whitehorses.soa.ums.entities.Status;
import nl.whitehorses.soa.ums.services.SessionEJB;

public class SessionEJBClient {
    public static void main(String[] args) {
        try {
            final Context context = getInitialContext();
            SessionEJB sessionEJB =
                (SessionEJB)context.lookup("SoaUMSMessaging-SessionEJB#nl.whitehorses.soa.ums.services.SessionEJB");

            List<Receiver> receivers = new ArrayList<Receiver>();
            Receiver receiver  = new Receiver("xxx@gmail.com", "EMAIL");
            Receiver receiver2 = new Receiver("xxxx@tiscali.nl", "EMAIL");
            receivers.add(receiver);
            receivers.add(receiver2);



            String messageId =
                sessionEJB.sendMailAttachmentMsg( "xxxx@xs4all.nl",
                                                   receivers,
                                                   "hello subject",
                                                   "hello body"
                                                   ,doDownload("C:/temp/logo.png"),
                                                   "image/png",
                                                   "logo.png");

            System.out.println("MessageId is " + messageId +
                               " lets wait 2 seconds for the status");
            Thread.sleep(2000);

            if (messageId != null) {
              List<Status> statusses =
                  sessionEJB.getMessageStatus(messageId);
              for (Status status : statusses) {
                  System.out.println(status.toString());
              }
            }


            Receiver receiver3 = new Receiver("nl2en@bot.talk.google.com", "IM");
            receivers.add(receiver3);

            messageId = sessionEJB.sendMixedMsg("Hello",
                                                "Hello world",
                                                "xxxx@xs4all.nl",
                                                receivers );


            System.out.println("MessageId is " + messageId +
                               " lets wait for the status");
            Thread.sleep(4000);

            if (messageId != null) {
                List<Status> statusses =
                    sessionEJB.getMessageStatus(messageId);
                for (Status status : statusses) {
                    System.out.println(status.toString());
                }
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static Context getInitialContext() throws NamingException {
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY,
                "weblogic.jndi.WLInitialContextFactory");
        env.put(Context.PROVIDER_URL, "t3://localhost:8001");
        return new InitialContext(env);
    }

    public static byte[] doDownload(String fileName) {
        FileInputStream fis;
        byte[] data = null;
        FileChannel fc;

        try {
            fis = new FileInputStream(fileName);
            fc = fis.getChannel();
            data = new byte[(int)(fc.size())];
            ByteBuffer bb = ByteBuffer.wrap(data);
            fc.read(bb);
        } catch (FileNotFoundException e) {
            // TODO
        } catch (IOException e) {
            // TODO
        }
        return data;
    }
}
If you send messages with this EJB Session or WS then you can take a look at the application client in the UMS service overview.

Here you can download my example workspace.