Archive for August 18th, 2008

WCF And MSMQ Part 1

Messaging technology allows a client and a server to send a message to each other, and they do not have to run at the same time. One party can send a message to another party at anytime. A crash on one side does not effect the another side.

In this tutorial, I am going to implement a simple WCF client-server application without any consideration on security. We are going to use MSMQ as a transport mechanism. I use Microsoft Visual Studio 2008. Please read Queuing in WCF msdn page for further information. Note: you have to install MSMQ on your computer.

Please refer to this msn page for what is WCF (Windows Communication Foundation) and what does it solves.

Please refer to this msdn page for various WCF technical term.

Each WCF service has an endpoint. An endpoint consists fo address, binding and contract.

- An address is usually a URI which specifies where the endpoint of the service is. 

- A binding defines the transport mechanism between a client and a server. There are some predefined bindings avaiable. In this tutorial, we are going to use MSMQ as a transport mechanism, so we are interested in NetMSMQBinding.

- A contract is your service, and it is implemented in C# in this tutorial.

Steps:

1. Create a server project

Create a server project by simply select a C# console application from “New Project” dialog.  Let’s name the solution name as wcf_tutorial” and the server project name as WCFServer1.”

New project and new solution dialog in Visual Studio 2008

New project and new solution dialog in Visual Studio 2008

Please refer to “How to Add or Remove References in Visual Studio” msdn page for how to add a reference.

You need to add two references which are System.messaging (found in .NET tab when opening up the “Add Reference” dialog) and System.ServiceModel.dll (found in “C:\WINDOWS\Microsoft.NET\Framework\v3.0\Windows Communication Foundation” in Windows folder, click on “Browse” tab in the “Add Reference” dialog).

2. Create server source files

 

IWork is an interface which will be configure as a contract in a binding configuration. WorkService is the implementation of this contract. The server does nothing. It just receives a string from a client.

Please refer to How to: Define a Windows Communication Foundation Service Contract msdn page for how define a contract. Please remember than a MSMQ is a messaging technology which is anynchronous communication. There is no respond back from a server like web service. Thus, the function has no return type which is “void.”

- Please refer to Build a Queued WCF Response Service for more information on WCF and MSMQ. 

- Please refer to How to: Implement a Windows Communication Foundation Service Contract msdn page for how to implement a contract.

//////Program.cs//////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Messaging;
using System.Configuration;

namespace WCFServer1
{

[ServiceContract(Namespace = "http://sukasom.wordpress.com")]
interface IWork
{

[OperationContract(IsOneWay = true)]
void submitWork(String str1);

}

public class WorkService : IWork
{

public void submitWork(String str1)
{

Console.WriteLine(“Server has received a work : “ + str1);

}

}

class Program
{

static void Main(string[] args)
{

 

string queueName = ConfigurationSettings.AppSettings["queueName"];

if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName, true);

using (ServiceHost serviceHost = new ServiceHost(typeof(WorkService)))
{

serviceHost.Open();

Console.WriteLine(“The service is ready.”);
Console.WriteLine(“Press <ENTER> to terminate service.”);
Console.ReadLine();

}

 

}

}

}

Put the above code in the Program.cs.  The server part is modified from How to: Host a WCF Service in a Managed Application msdn page.

3. Configure server configuration file

You need to configure the configuration file. Add an App.config file into your project. Please refer to Specifying an Endpoint Address msdn page for more information on address configuration. My configuration file is modified from NetMSMQBinding msdn page.

Configuration of WCF service using MSMQ as a transport mechanism

Configuration of WCF service using MSMQ as a transport mechanism

///////////////App.config /////////////////////////

<?xml version=”1.0” encoding=”utf-8?>
<configuration>

<appSettings>
<add key=”queueName” value=”.\private$\ServiceModelSamples/>
</appSettings>

<system.serviceModel>
<services>

<service name=”WCFServer1.WorkService” behaviorConfiguration=”Behavior1>

<endpoint address=”net.msmq://localhost/private/ServiceModelSamples
binding=”netMsmqBinding” bindingConfiguration=”test
contract=”WCFServer1.IWork/>

</service>

</services>

<!– Following is necessary for getting information about the service through http with the svcutil.exe tool. –>
<behaviors>
<serviceBehaviors>

<behavior name=”Behavior1>

<serviceMetadata httpGetEnabled=”true” httpGetUrl=”http://localhost:8000/Hello//>

</behavior>

</serviceBehaviors>
</behaviors>

<!– For first example, the security is just disabled. –>
<bindings>

<netMsmqBinding>

<binding name=”test>

<security mode=”None>
</security>

</binding>

</netMsmqBinding>

</bindings>

</system.serviceModel>

</configuration>

In the “service” element, an endpoint is defined with an address, a binding and a contract. This WCF sample application uses MSMQ as a transport mechanism, so the binding is the NetMsmqBinding. 

The contract specifies the interface which is WCFServer1.IWork. The security is turned off in this tutorial through the bindingConfiguration named “test.”

A client needs to be able to access the metadata of the service, so  it is defined through the behaviorConfiguration  named “Behavior1″ where the httpGetEnabled attribute is set to true. It means that  the metadata can be retrieved through the http through the URL set in the httpGetUrl attribute which is “http://localhost:8000/Hello/” in this tutorial. This URL allows the client to get a metadata about the service from the correct location. You can open up the http://localhost:8000/Hello/ on the browser as shown below.

Metadata on the service

Metadata on the service

More info on address and httpGetEnabled can be found in WCF Part 6 : Address blog.

4. Implement the client project.

Start a visual studio 2008 and add a new C# console project as shown in the figure below. The name of the project is “WCFClient1.” Just like the server part, add the reference to System.ServiceModel.dll. More info on accessing service through a client at Accessing Services Using a WCF Client msdn page.

Add new project into an existing solution in microsoft visual studio 2008

Add new project into an existing solution in microsoft visual studio 2008

5. Generate a client proxy.

The ServiceModel Metadata Utility Tool (Svcutil.exe) is needed to generate the proxy file for a client. The proxy file allows you to treat a remote service as a local service. You simply instantiate a remote object and call a function on it. This is much simple compared with some old distributed technologies.

Please refer to ServiceModel Metadata Utility Tool (Svcutil.exe) msdn page for the manaul of Svcutil.exe.

Please start the server first then type the following command in the command prompt.

“C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcUtil.exe”  http://localhost:8000/Hello/

The URI is the URI that is defined in the App.config in the server part. After running the above command, you will get two files which are WorkService.cs and output.config.

Generating a proxy file for a WCF client project using SvcUtil.exe

Generating a proxy file for a WCF client project using SvcUtil.exe

Please rename the output.config to App.config. Copy those two files into your project directory, and add those files into your project.

Following is the code for the client:

////////////Program.cs in the client part/////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WCFClient1
{

class Program
{

static void Main(string[] args)
{

WorkClient wc = new WorkClient();
wc.submitWork(“hello work 1″);

}

}

}

Calling a server is very simple, instantiating the proxy object and calling a function on it. You can see that there is a class called WorkClient defined in the WorkService.cs. Please run the server first. If the queue has not been created, it will be created. When the queue is created, you don’t have to run the server before running the client. You can run the client first, and the message from the client will be stored in the queue. The message will be sent to the server when the server is started again.

 

Server part

Server part

You can take a look Tom Hollander’s blog for another good tutorial on this topic.

Here is the complete source code.

The book from [Lowy] is also good.

1 comment August 18, 2008

JMS Topic

I had taken a lab course with this department. Without the lab assistant, I would not make it through. I would like to summarize a part of my lab work here related with JMS, so I will not forget. Full lab report here.

Following is the general architecture of  the system. JMS is used for communication between the NodeController and a Node Client.

 

The Overview Architecture of the Job Spooling System

The Overview Architecture of the Job Spooling System

 

 

I was doing a distributed application in Java. Part of the lab is sending a message from an EJB (version 3) to a client application on a different machine using JMS (Java Message Service).  First, we have to create a JMS Topic which is kind of a channel that we send can send a message too. Naming this technology with the word “Topic” is not a good idea, because this word is a common name. Thus, it is difficult to search for examples in Google.

 

I was using JBoss 4. I had to create a JMS Topic in the JBoss first by going to the JMX console of JBoss. I assume that you know how to install JBoss, and develop  EJB 3.0 applications.

1. Go to JBoss homepage at http://localhost:8080. The URL could be something else that you have set.

2. Go to JMX console by clicking at JMX Console under JBoss management.

3. Go to DestinationManager under jboss.mq.

4. Create a JMS topic named “pomtopic” by invoking the createTopic function. Supply param p1 and p2 with the value “pomtopic,” and then click “Invoke” as shown in the figure below. The “pomtopic” topic will be
created. Java application can send message to and receive message from this JMS topic.

I am not sure why there are two paramters (p1 and p2). Just try to use the same name. The name could be something else. The name will be referenced from the codes.

Creating a JMS Topic within a JMX Console of JBoss 4. Clicking invoke will create a JMS Topic.

Creating a JMS Topic within a JMX Console of JBoss 4. Clicking invoke will create a JMS Topic.

Following is the sender code of the JMS Topic. The sender code is in the EJB 3.0. Some variables are declared and instantiated automatically though dependency injection technique.

==========sender=============================

……

// Connection factory for JMS Topic communication
@Resource(mappedName=”TopicConnectionFactory”)
private ConnectionFactory connectionFactory;
//For JMS Topic communication, the name of JMS Topic is fixed to “pomtopic”.
//This topic must be created in JBoss JMX console before using, otherwise, it will throw an exception.

@Resource(mappedName=”pomtopic”)
private Topic topic;

// This function will send the message to the JMS topic.
//Derived from the JMS tutorial from Sun website
// @param msg represents the message that this function will send to the JMS topic which node client is //listening to.
//@return result of sending, True for successfully. False for when there is an exception occurred.

public boolean sendMessageToTopic(String msg)
{

try {

Connection connect = connectionFactory.createConnection( );
Session session = connect.createSession(true,0);
MessageProducer producer = session.createProducer(topic);
TextMessage textMsg = session.createTextMessage( );
textMsg.setText(msg);
producer.send(textMsg);
connect.close( );

 

} catch (JMSException ex) {

logger.debug(ex.getMessage());
return false;

 

}
return true;

 

}

….

==================================================

 

Next is the client code who is waiting for message. First, you need to create a connection to the JMS Topic first. The Java function below demonstrates the connection.

=====client : function for creating a JMS Topic connection=============

public  void connectByTopic() {

String                  topicName = null;
Context                 jndiContext = null;
TopicConnectionFactory  topicConnectionFactory = null;
TopicConnection         topicConnection = null;
TopicSession            topicSession = null;
Topic                   topic = null;
TopicSubscriber         topicSubscriber = null;

/*  Part of Code from Sun
* Create a JNDI API InitialContext object if none exists
* yet.
*/

try {

jndiContext =getInitialContext();// new InitialContext();

} catch (NamingException e) {

System.out.println(“Could not create JNDI API ” +
“context: ” + e.toString());
e.printStackTrace();
System.exit(1);

}

/*
* Look up connection factory and topic.  If either does
* not exist, exit.
*/

try {

topicConnectionFactory = (TopicConnectionFactory)
jndiContext.lookup(“TopicConnectionFactory”);
topic = (Topic) jndiContext.lookup(“pomtopic”);

} catch (NamingException e) {

System.out.println(“JNDI API lookup failed: ” +
e.toString());
e.printStackTrace();
System.exit(1);

}

/*
* Create connection.
* Create session from connection; false means session is
* not transacted.
* Create subscriber.
* Register message listener (TextListener).
* Receive text messages from topic.
* When all messages have been received, enter Q to quit.
* Close connection.
*/

try {

topicConnection = topicConnectionFactory.createTopicConnection();
topicSession =  topicConnection.createTopicSession(false,
Session.AUTO_ACKNOWLEDGE);
topicSubscriber = topicSession.createSubscriber(topic);
topicSubscriber.setMessageListener(this);
topicConnection.start();

 

} catch (JMSException e) {

System.out.println(“Exception occurred: ” +
e.toString());

} finally {

if (topicConnection != null) {
try {
topicConnection.close();
} catch (JMSException e) {}
}

}

}
==================================================

After creating a JMS Topic connection, then the Java client application needs to listen for a message.

=========Client : function for listening a JMS Topic message==========

public void onMessage(Message message) {

TextMessage msg = null;
try {

if (message instanceof TextMessage) {

msg = (TextMessage) message;
System.out.println(“Reading message: ” +
msg.getText());

//the following function will process the message sent from the server
processMessageAndExecute(msg.getText());

 

} else {

System.out.println(“Message of wrong type: ” +

message.getClass().getName());

}

} catch (JMSException e) {

System.out.println(“JMSException in onMessage(): ” +
e.toString());

} catch (Throwable t) {

System.out.println(“Exception in onMessage():” +
t.getMessage());

}

}

=================================================

Add comment August 18, 2008


Categories

Top Posts

Recent Posts

Pages

Archives

 

August 2008
M T W T F S S
« Jul   Sep »
 123
45678910
11121314151617
18192021222324
25262728293031

Blogroll

Books

Blog Stats

Top Clicks

Category Cloud

database Distributed application Education emergency response entrepreneurship firefighter (Feuerwehr) Flex/Flash German Language (Deutsch) Java Microsoft and .NET Risk Management (Disaster) Software Testing Uncategorized User Interface Design and Technology wcf Windows Workflow

Spam Blocked