Creating a Web Service in Microsoft.NET, and consuming from WebLogic's Web Client


According to Microsoft.NET, Web Services are not inherently service-oriented-they represent a solution to implementing a SOA strategy. Web Services provide a necessary standards-based implementation of SOA wherein services are described using WSDL and accessed via SOAP. So that interoperability across platform, organizational, and network boundaries is feasible. Web Services technologies implemented by the .NET distributed computing model can support such a strategy.

Web Services are logic units that allow programs written in different programming languages and on different platforms to communicate through standard Internet protocols. Microsoft has stated:  "XML Web Services platform will enable developers to create programs that transcend device boundaries and fully harness the connectivity of the Internet."

Web Services allow applications, which may be written in different programming languages or on different platforms, to communicate and share data through standard Internet protocols.

Implementing a Web Services in Microsoft.NET

Microsoft.NET includes a good support for Web Services. Using Visual Studio .NET let's create Web Services implementations from a project template. Whether we create our Web Services in Microsoft.NET Framework or in Java, there are several common concepts, such as, we have a business object implementing some logic and we want to provide such behavior as a Service to other elements.

Creating Web Services in .NET Framework
Web services are tightly integrated into the .NET Framework. It's very easy to use the Visual Studio .NET to design and create a Web service. The .NET Web services implementation uses the same page framework as ASP.NET, consisting of the following:

  • URL for accessing the Web Service (.asmx file).
  • The code behind which implement the Web Service's behavior. It might be a backend object providing its behavior through the Web Service.

Using Visual Studio .NET, we may create an ASP.NET Web service project in any of the supported languages using the Web service project templates (File -> New -> Project -> ASP.NET Web Application).

After we create an ASP.NET Web service project in Visual Studio, it's constructed a Web application project structure, that is the .asmx file and the code behind associated for each Web Services and the references to external components, on the Web server which we have chosen and a Visual Studio solution file on our local computer which contains the configuration and build settings and keeps a list of files associated with the project.

We are going to model the Purchase Order Information object using the Business Entity POInfo as information holder. The logic of our Web Service is very simple. The contract to the clients is composed by two operations, first one is initializing a standard Purchase Order, and the second one is receiving a Purchase Object serialized in XML as a message and make some changes in its state such shipping date, the user id, etc.

We can implement the functionality of a Web Services using a class, and marking with attributes the context of the class and the exportable methods (Aspect-Oriented programming).

Using the WebServiceAttribute attribute object we may specify the context of the instance of our WebService such as a description, a name and its namespace. Using the WebMethodAttribute attribute object we may configure aspects of the available method such as its name and a description, whether the messaging is buffered or not, whether it's bound to a session for implementing a stateful services.

Listing 1 shows the definition of the POInfo information holder (Purchase Order Information Business Entity), and in listing 2 the implementation of the PurchaseOrder Web Service.

using System;
namespace WSTest
{
public class POInfo
{
private int m_nId=0;
private string m_strLastName=null;
private string m_strFirstName=null;
private DateTime m_dtShipping=DateTime.Now;
private int m_nAmount=0;
public POInfo()
{}
public int Id
{
get
{
return this.m_nId;
}
set
{
this.m_nId=value;
}
}
public string LastName
{
get
{
return this.m_strLastName;
}
set
{
this.m_strLastName=value;
}
}
public string FirstName
{
get
{
return this.m_strFirstName;
}
set
{
this.m_strFirstName=value;
}
}
public DateTime Shipping
{
get
{
return this.m_dtShipping;
}
set
{
this.m_dtShipping=value;
}
}
public int Amount
{
get
{
return this.m_nAmount;
}
set
{
this.m_nAmount=value;
}
}
}
}

Listing 1.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
namespace WSTest
{
/// <summary>
/// Summary description for PurchaseOrder.
/// </summary>
///
[WebService(Namespace=http://www.olamendy.com/)]
public class PurchaseOrder : System.Web.Services.WebService
{
public PurchaseOrder()
{
//CODEGEN: This call is required by the ASP.NET Web Services Designer
InitializeComponent();
}
#region Component Designer generated code
//Required by the Web Services Designer
private IContainer components = null;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if(disposing && components != null)
{
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
// WEB SERVICE EXAMPLE
// The HelloWorld() example service returns the string Hello World
// To build, uncomment the following lines then save and build the project
// To test this web service, press F5
[WebMethod]
public POInfo GetPurchaseOrderInfo()
{
POInfo objInfo=
new POInfo();
objInfo.Amount=10;
objInfo.FirstName="John Charles";
objInfo.LastName="Olamendy";
objInfo.Id=3;
objInfo.Shipping=DateTime.Now;
return objInfo;
}
[WebMethod]
public POInfo ProcessPurchaseOrderInfo(POInfo objInfo)
{
objInfo.Amount=objInfo.Amount+1;
objInfo.FirstName=objInfo.FirstName+":C";
objInfo.LastName=objInfo.LastName+":C";
objInfo.Id=objInfo.Id+1;
objInfo.Shipping=objInfo.Shipping.AddDays(1);
return objInfo;
}
}
}

Listing 2.

After we build a Web service, ASP.NET automatically provides the infrastructure and handles the processing of Web service requests and responses such as the serialization and de serialization of the involved objects and the creation of SOAP messages. We may access to this WebServices using the URL pointing to .asmx file, for instance http://localhost/WSTest/PurchaseOrder.asmx .It is also created a test page for the Web Services for watching its behavior.

Creating a WebCient in BEA WebLogic which consumes the Web Services.

After we create our Web service, we need to have client applications to access it. There are several ways of doing this, depending on the protocols that our Web service supports.

If our Web service supports the HTTP-GET protocol, we can access it from a Web browser. By default, Web services that we create in Visual Studio using the ASP.NET Web service project template support HTTP-GET, HTTP-POST, and HTTP-SOAP. In our case, we're going to access unsing HTTP-SOAP.

We're going to create an application in BEA WebLogic, File->New->Application->Default Application. Then, it is created a J2EE application, and inside the former, a Web Module.

First of all, we must access to the Web Service's contract for taking the description of all operations and using the URL http://localhost/WSTest/PurchaseOrder.asmx?wsdl it is download an XML application where all the operations, the messages and transport protocol are specified. Then save this document as PurchaseOrder.wsdl inside our WebLogic Web Module. Then using the WebLogic Workshop's Application View browse to the file PurchaseOrder.wsdl right-click and choose Generate Service Control generating all the plumbing for the messaging on behalf of us with the Web Services protocol stack, such PurchaseOrderControl which is a Java Control acting a proxy with the real Web Service, and all the XML persistent data types for creating the messages.

Listing 3 shows the generated code.

package ControlRef;

/**
 * @jc:location http-url="
http://localhost/wstest/PurchaseOrder.asmx"
 * @jc:wsdl file="#PurchaseOrderWsdl"
 * @editor-info:link source="PurchaseOrder.wsdl" autogen="true"
 */
public interface PurchaseOrderControl extends com.bea.control.ControlExtension, com.bea.control.ServiceControl
{
    public static class POInfo
        implements java.io.Serializable
    {
        public int Id;
        public java.lang.String LastName;
        public java.lang.String FirstName;
        public java.util.Calendar Shipping;
        public int Amount;
    }
   
   
    /**
     * @jc:protocol form-post="false" form-get="false"
     */
    public POInfo GetPurchaseOrderInfo ();

    /**
     * @jc:protocol form-post="false" form-get="false"
     */
    public POInfo ProcessPurchaseOrderInfo (POInfo objInfo);

    static final long serialVersionUID = 1L;
}

/** @common:define name="PurchaseOrderWsdl" value::
    <?xml version="1.0" encoding="utf-8"?>
    <wsdl:definitions xmlns:http="
http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://www.olamendy.com/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://www.olamendy.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
      <wsdl:types>
        <s:schema elementFormDefault="qualified" targetNamespace="
http://www.olamendy.com/">
          <s:element name="GetPurchaseOrderInfo">
            <s:complexType />
          </s:element>
          <s:element name="GetPurchaseOrderInfoResponse">
            <s:complexType>
              <s:sequence>
                <s:element minOccurs="0" maxOccurs="1" name="GetPurchaseOrderInfoResult" type="tns:POInfo" />
              </s:sequence>
            </s:complexType>
          </s:element>
          <s:complexType name="POInfo">
            <s:sequence>
              <s:element minOccurs="1" maxOccurs="1" name="Id" type="s:int" />
              <s:element minOccurs="0" maxOccurs="1" name="LastName" type="s:string" />
              <s:element minOccurs="0" maxOccurs="1" name="FirstName" type="s:string" />
              <s:element minOccurs="1" maxOccurs="1" name="Shipping" type="s:dateTime" />
              <s:element minOccurs="1" maxOccurs="1" name="Amount" type="s:int" />
            </s:sequence>
          </s:complexType>
          <s:element name="ProcessPurchaseOrderInfo">
            <s:complexType>
              <s:sequence>
                <s:element minOccurs="0" maxOccurs="1" name="objInfo" type="tns:POInfo" />
              </s:sequence>
            </s:complexType>
          </s:element>
          <s:element name="ProcessPurchaseOrderInfoResponse">
            <s:complexType>
              <s:sequence>
                <s:element minOccurs="0" maxOccurs="1" name="ProcessPurchaseOrderInfoResult" type="tns:POInfo" />
              </s:sequence>
            </s:complexType>
          </s:element>
        </s:schema>
      </wsdl:types>
      <wsdl:message name="GetPurchaseOrderInfoSoapIn">
        <wsdl:part name="parameters" element="tns:GetPurchaseOrderInfo" />
      </wsdl:message>
      <wsdl:message name="GetPurchaseOrderInfoSoapOut">
        <wsdl:part name="parameters" element="tns:GetPurchaseOrderInfoResponse" />
      </wsdl:message>
      <wsdl:message name="ProcessPurchaseOrderInfoSoapIn">
        <wsdl:part name="parameters" element="tns:ProcessPurchaseOrderInfo" />
      </wsdl:message>
      <wsdl:message name="ProcessPurchaseOrderInfoSoapOut">
        <wsdl:part name="parameters" element="tns:ProcessPurchaseOrderInfoResponse" />
      </wsdl:message>
      <wsdl:portType name="PurchaseOrderSoap">
        <wsdl:operation name="GetPurchaseOrderInfo">
          <wsdl:input message="tns:GetPurchaseOrderInfoSoapIn" />
          <wsdl:output message="tns:GetPurchaseOrderInfoSoapOut" />
        </wsdl:operation>
        <wsdl:operation name="ProcessPurchaseOrderInfo">
          <wsdl:input message="tns:ProcessPurchaseOrderInfoSoapIn" />
          <wsdl:output message="tns:ProcessPurchaseOrderInfoSoapOut" />
        </wsdl:operation>
      </wsdl:portType>
      <wsdl:binding name="PurchaseOrderSoap" type="tns:PurchaseOrderSoap">
        <soap:binding transport="
http://schemas.xmlsoap.org/soap/http" style="document" />
        <wsdl:operation name="GetPurchaseOrderInfo">
          <soap:operation soapAction="
http://www.olamendy.com/GetPurchaseOrderInfo" style="document" />
          <wsdl:input>
            <soap:body use="literal" />
          </wsdl:input>
          <wsdl:output>
            <soap:body use="literal" />
          </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="ProcessPurchaseOrderInfo">
          <soap:operation soapAction="
http://www.olamendy.com/ProcessPurchaseOrderInfo" style="document" />
          <wsdl:input>
            <soap:body use="literal" />
          </wsdl:input>
          <wsdl:output>
            <soap:body use="literal" />
          </wsdl:output>
        </wsdl:operation>
      </wsdl:binding>
      <wsdl:service name="PurchaseOrder">
        <wsdl:port name="PurchaseOrderSoap" binding="tns:PurchaseOrderSoap">
          <soap:address location="
http://localhost/wstest/PurchaseOrder.asmx" />
        </wsdl:port>
      </wsdl:service>
    </wsdl:definitions>
 * ::
 */

Listing 3.

Using Model-View-Controller design pattern is very easy in WebLogic. We may define the flow of the pages using the PageFlowController class, an instance of the class PageFlowController manages all the pages, loading the right page according to the flow definition and calling the application logic on behalf of the pages using the actions.


 
In this case, when application starts, it is loaded the page index.jsp for gathering user information, then the user triggers the getPurchaseOrder action, for calling the logic of the application and doing some operations, in our case it is an access to the former PurchaseOrder Web Service, sending a messages and waiting a response message using the SOAP/HTTP as a transport protocol. Finally the message is received, the page response.jsp is loaded and the information is shown to user.

In the definition of the PageFlowController, it is created an instance of the Java Control PurchaseOrderControl for accessing the Web Service, and it's also define a reference to the object Purchase Order received from the messaging.

The code of the getPurchaseOrder action is shown in the listing 4.
  
 /**
     * @jpf:action
     * @jpf:forward name="success" path="response.jsp"
     */
    protected Forward getPurchaseOrder(GetPurchaseOrderForm form)
    {
        ControlRef.PurchaseOrderControl.POInfo objInfo=new ControlRef.PurchaseOrderControl.POInfo();
        objInfo.Amount=form.amount;
        objInfo.FirstName=form.firstname;
        objInfo.Id=form.id;
        objInfo.LastName=form.lastname;
        objInfo.Shipping=java.util.Calendar.getInstance();
       
        this.POInfo=this.purchaseOrderControl.ProcessPurchaseOrderInfo(objInfo);
        return new Forward("success");
    }

Listing 4.

It is created an instance of POInfo class and filled the state with the gathered information from index.jsp. Then it is called the operation ProcessPurchaseOrderInfo in the instance of PurchaseOrder proxy control, which receives a POInfo object, serializes it to XML and then passes it to the Web Services stack.

Conclusion

This article explains the step necessary to create a Web Service in Microsoft.NET and consume it from a Web Client in BEA WebLogic. It is touched important aspects of Microsoft.NET technologies for Web Services, and BEA WebLogic technologies for implement the Model-View-Controller design pattern.


Similar Articles