Self-hosted WCF services can use WebORB to expose themselves to the client applications capable to speak the AMF protocol. This includes Flash and Flex applications, Java and .NET applications using the WebORB client APIs (both WebORB for Java and WebORB for .NET provide APIs for server-to-server or app-to-app communication).
To expose a self-hosted WCF service via a dedicated AMF endpoint:
| 1. | Add weborb.dll as a reference to your Visual Studio project |
| 2. | Copy weborb.config into the directory containing the executable for the self-hosted service |
| 3. | Use the AddAmfEndpoint method on the ServiceHost class as shown below (the code below uses the sample StockQuoteService): |
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Weborb.Examples.WCF;
using Weborb.Handler.WCFServiceModel.Description;
using Weborb.Handler.WCFServiceModel.Configuration;
namespace WCFAMFTest
{
class Program
{
static void Main( string[] args )
{
String serviceURL = "http://localhost:8000/WCFAMFExample"
// Create a URI to serve as the base address.
Uri baseAddress = new Uri( serviceURL );
// Create ServiceHost
ServiceHost selfHost = new ServiceHost( typeof( StockQuoteService ), baseAddress );
try
{
// Add AMF endpoint
ServiceEndpoint endpoint = selfHost.AddAmfEndpoint( typeof( IStockQuoteService ) );
// Start the service.
selfHost.Open();
Console.WriteLine( "The service is ready" );
Console.WriteLine( "AMF Service URL is " + serviceURL + "/amf" );
Console.WriteLine( "Press <ENTER> to terminate service." );
Console.ReadLine();
// Close the ServiceHostBase to shutdown the service.
selfHost.Close();
}
catch( CommunicationException ce )
{
Console.WriteLine( "An exception occurred: {0}", ce.Message );
selfHost.Abort();
}
}
}
}
Invoking Self-Hosted Service From Flex/AIR
Flex and AIR clients can use the RemoteObject API to invoke methods on self-hosted WCF services which use the AMF endpoint. There are two approaches for invoking self-hosted WCF service. The first approach requires less code, but creates a dependency on configuration files declaring destinations and channels (the files located in WEB-INF/flex). The second approach does not have any dependencies on the configuration files, but results in a few additional lines of code.Consider the examples of the API below:
Approach 1 (with dependency on configuration files):
var remoteObject:RemoteObject = new RemoteObject("GenericDestination");
remoteObject.endpoint = "http://localhost:8000/WCFAMFExample/amf"
remoteObject.GetQuote.addEventListener( ResultEvent.RESULT, gotResult );
remoteObject.GetQuote.addEventListener( FaultEvent.FAULT, gotError );
remoteObject.GetQuote( "name" );
The endpoint URL uniquely identifies the WCF service. Notice the /amf at the end of the URL, it is required for the AMF endpoint. With the approach demonstrated above, the destination name in the RemoteObject constructor is required however it is not used. As a result, for the code to work, the Flex/AIR application must be compiled with additional compile argument:
-services "C:\Program Files\WebORB for .NET\4.0\web-inf\flex\services-config.xml"
Approach 2 (without dependency on configuration files):
var remoteObject:RemoteObject = new RemoteObject();
var channelSet:ChannelSet = new ChannelSet();
var amfChannel:AMFChannel = new AMFChannel( "wcfAmf", "http://localhost:8000/WCFAMFExample/amf" );
channelSet.addChannel( amfChannel );
remoteObject.channelSet = channelSet;
remoteObject.GetQuote.addEventListener( ResultEvent.RESULT, gotResult );
remoteObject.GetQuote.addEventListener( FaultEvent.FAULT, gotError );
remoteObject.GetQuote( "name" );
For both approaches to create a Flex project where the code shown above can be used, follow the instructions from the Flex and WebORB quick start guide. For approach 2 the step where additional compiler argument is added is not required.
Invoking Self-Hosted Service From Java
A WCF self-hosted service with the AMF behavior can be invoked from a Java application using the WeborbClient API available in WebORB for Java. The code below demonstrates the API:
import weborb.client.Fault;
import weborb.client.IResponder;
import weborb.client.WeborbClient;
import weborb.types.Types;
public class WCFInvoker implements IResponder
{
public static void main(String[] args) throws Exception
{
Types.addClientClassMapping( "Weborb.Examples.WCF.StockQuote", StockQuote.class );
WeborbClient weborbClient = new WeborbClient( "http://localhost:8000/WCFAMFExample/amf" );
weborbClient.invoke( "GetQuote", new Object[] { "MSFT" }, new WCFInvoker() );
}
public void responseHandler( Object adaptedObject )
{
Object[] result = (Object[]) adaptedObject;
StockQuote quote = (StockQuote) result[ 0 ];
System.out.println( "Received response: ");
System.out.println( "Bid: " + quote.getBid() );
System.out.println( "Ask: " + quote.getAsk() );
System.out.println( "Last: " + quote.getLast() );
System.out.println( "Last transaction time: " + quote.getLastTxTime() );
}
public void errorHandler( Fault fault )
{
System.out.println( "Received error: " + fault.getMessage() );
}
}
There are several key points for the WCFInvoker example:
| • | The Types.addClientClassMapping() method creates a class mapping between the .NET and the corresponding Java class (listing of the Java StockQuote class is below) |
| • | The WeborbClient constructor accepts the AMF endpoint URL of the WCF service |
| • | weborbClient.invoke invokes the GetQuote method with the argument list identified by the Object[] array. The third parameter in the call is an instance of the IResponder interface. |
| • | Because of the class mapping in place, the returned object is automatically adapted to the Java class. The return value is always an array of one element - the StockQuote object is the first element of the array. |
The StockQuote Java class is shown below:
import java.util.Date;
public class StockQuote
{
private double Last;
private double Ask;
private double Bid;
private Date LastTxTime;
public double getLast() { return Last; }
public void setLast( double last ) { this.Last = last; }
public double getAsk() { return Ask; }
public void setAsk( double ask ) { this.Ask = ask; }
public double getBid() { return Bid; }
public void setBid( double bid ) { this.Bid = bid; }
public Date getLastTxTime() { return LastTxTime; }
public void setLastTxTime( Date lastTxTime ) { this.LastTxTime = lastTxTime; }
}
Notice the names of the private fields match the names of the DataMembers in the Data Contract. This is intentional to enable automatic mapping between .NET and Java types. To override the default mapping, see client/server field/property mapping.
The following Jar files are required to run the Java code using the WeborbClient API:
| • | weborb.jar |
| • | jdom-1.1.jar |
| • | commons-codec-1.3.jar (or newer) |
| • | commons-httpclient-3.1.jar (or newer) |
| • | commons-logging-1.1.jar (or newer) |
Finally, make sure to add weborb-config.xml to the Java application's CLASSPATH.