Showing posts with label web services. Show all posts
Showing posts with label web services. Show all posts

Create WSDL in Apache obfiz | Create web services in Apache ofbiz | Apache ofbiz web services tutorial.

In my project there is requirement of web services integration with Microsoft BizTalk i.e. Through WSDL
Biztalk will communicate with Apache ofbiz Services.

Following below step to follow for exposed ofbiz service to as web Services

1. Create a Apache ofbiz Services as below
   package org.ofbiz.party.party;

import java.util.Map;

import javolution.util.FastMap;

import org.ofbiz.service.DispatchContext;

public class TestWebService {
   
   
      public static Map<String, Object> testWebSerice(DispatchContext ctx, Map<String, ? extends Object> context) {
         
          Map<String, Object> result = FastMap.newInstance();
        try
        {
          String username=(String) context.get("userName");
         
          if(username.equals("kumud"))
          {
              result.put("returnMsg", "Hi Kumud") ;
          }
          else
          {
              result.put("returnMsg", "You are not kumud") ;
          }
         
          return result;
         
      }
     
      catch(Exception ex)
      {
          ex.fillInStackTrace();
          result.put("returnMsg", "Hi Kumud") ;
          return result;
      }
}
}


2. Register service in services.xml file as below

 <service name="TestWebSerice" engine="java" auth="false"
            location="org.ofbiz.party.party.TestWebService" invoke="testWebSerice"  export="false">
        <description>Test Web Service  by kumud</description>
       
        <attribute name="userName" type="String" mode="IN" optional="false"/>
        <attribute name="returnMsg" type="String" mode="OUT" optional="false"/>
       
    </service>

3. For expose above service as Web Services by making  export="true" in above configuration

   <service name="TestWebSerice" engine="java" auth="false"
            location="org.ofbiz.party.party.TestWebService" invoke="testWebSerice"  export="true">
        <description>Test Web Service  by kumud</description>
       
        <attribute name="userName" type="String" mode="IN" optional="false"/>
        <attribute name="returnMsg" type="String" mode="OUT" optional="false"/>
       
    </service>
   
4. Now start server hit by url http://localhost:8080/webtools/control/SOAPService/TestWebSerice?wsdl in web browser
   there show WSDL file

Step by Step to create web services in Hybris e-commerce suit | E-commerce domain ERP

Create a new extension

We will create a new extension similar to the one already covered in Trail+~New+Extension, to expose our webservice. However we won't define any new Items in the data model.
  1. Open the Ant view in Eclipse and invoke the platform's task extgen
    1. Enter the name "cuppywstrail" for the extension WHICH MUST BE ONE WORD IN LOWER CASE
    2. Enter the package prefix "de.hybris.platform.cuppywstrail" also WHICH MUST BE ALL IN LOWER CASE
    3. Select yempty for the extension template
  2. The Ant script will now create a skeleton extension for you in <YOURPATH>/bin/custom/cuppywstrail but this is not yet imported into Eclipse
  3. Import the generated extension into your Eclipse environment
    1. Right-click in package explorer and select Import
    2. Select General|Existing Projects into Workspace and browse to the new extension <YOURPATH>/bin/custom/cuppywstrail
    3. Remember to ensure that the "Copy projects into workspace" check box is not checked before clicking on the Finish button
    4. You should now see the extension in your Eclipse Package Explorer
    5. You can ignore any build errors currently being reported as the configuration is not yet complete
  4. Append the new extension to config/localextensions.xml file in the config project:
    config/localextensions.xml
    ...
       <extension dir="${HYBRIS_BIN_DIR}/custom/cuppywstrail"/>
    </extensions>
  5. Run Ant's all task from Eclipse
    1. This will generate the Java Source files representing the Data Entities ("items") in all the -items.xml files (see buildprocessessentials for an overview)
    2. See the output in Eclipse's console view and wait for completion
  6. Load the generated files into Eclipse and build
    1. Select all top-level projects in the Package Explorer, right-click and select refresh - this will reload all generated files into Eclipse
    2. Ensure that in Eclipse the option Project|Build Automatically is checked
    3. Eclipse will now start to build your project
  7. Explore your new extension's structure
  8. Run hybris and ensure your new extension is accessible
    1. Start hybris (by executing hybrisserver.bat or ./hybrisserver.sh from the command line in the directory <YOURPATH>/bin/platform)
    2. Open http://localhost:9001/cuppywstrail and verify that you get a simple message with the extension name, "cuppywstrail" and "welcome to my extension" below it.
    3. You can also verify that your extension is running by opening http://localhost:9001 under Platform/Extensions. You should see "cuppywstrail" in the list.

      This tells you that the extension is now running

Generated Classes

As discussed in Trail+~+New+Data+Model, the hybris build framework generates a number of java source files for each item type defined in items.xml. This includes:
  • models created for the service layer (business logic should go there)
  • classes created to support CRUD logic via RESTful URIs
  • low-level Jalo classes which we won't discuss as their use is discouraged
We will now explore the classes generated for supporting the CRUD cycle through RESTful webservice calls.
A Stadium Data Entity is defined in cuppytrail's items.xml file. As described in Trail+~+New+Data+Model, we should expect to see several files generated for this entity including DTOs and Resources. These were created for the cuppytrail extension where we defined the Item type Stadium. It is important to note that they are actually created in the platform project. To verify that these classes exist, search for them in Eclipse, using the Navigate Menu / Open Type, or the shortcut key Ctrl-Shift-T. If you search for "StadiumDTO", for example, you will see that it has been created in the platform project, in the package de/hybris/platform/cuppytrail/dto which is located in the web/gensrc folder.
  • Since DTOs and Resources are located in the platform's web folder, they are in the web-layer of the platform. If we try and reference them in code which is in our web layer, i.e. the web folder of the cuppywstrail extension, they will not be in the build path. Web-layers within separate extensions are not able to see each other's classes. Eclipse handles this by dynamically applying a build path to the entire workspace, but when you build your project with Ant, any references you make, for example to the data transfer object for Stadium, will result in a build failure. Individual web applications do not share the same class loaders which matches the final deployment scenario. However this usually turns out to be quite inconvenient for developing and deploying.
  • Next we will see how to solve this problem.

Webservice nature

To allow the cuppywstrail extension to expose the Stadium item type to a web service client, we need to do two things:
First, we need make the cuppywstrail extension visible to the cuppytrail extension where the Stadium class is defined.
Add the following tags inside the extension tag in extensioninfo.xml of the cuppywstrail project.
extensioninfo.xml
<requires-extension name="cuppy"/>
<requires-extension name="cuppytrail"/>
Next we need include the generated DTOs and Resources from cuppytrail in our classpath.
This is done by assigning cuppywstrail a "webservice nature which generates the file core-webservices.jar containing the platform's generated DTOs and Resources in cuppywstrail/webroot/WEB-INF/lib. As the folder is included in cuppywstrail's classpath, we can now reference and extend the DTOs and Resources. A new web.xml file will be created, as well as the file cuppywstrail/resources/cuppywstrail-web-spring.xml redirecting requests to our webservice request handler.

  • In Eclipse, drag the file cuppywstrail/build.xml into your Ant View.
  • Select the cuppywstrail target webservice_nature
  • Clean your extension by running your extension's ant clean (Note this is not the platform clean's ant task)
  • Finally run the platform all ant task
The DTO class will be extended later to demonstrate how to customise DTO and Resource behaviour.
Let's summarize the previous steps:
  • we created a new extension referencing the cuppytrail extension
  • classes in this extension were not able to access the generated DTOs and Resources because they reside in the platform's web-layer
  • we assigned a webservice nature to cuppywstrail and rebuilt the system resulting in a jar (core-webservices.jar) with DTOs and resources from the cuppytrail extension to be copied to cuppywstrail

Webservice support for the Stadium Data Entity

We have now we have enabled web service support for the Stadium Data Entity.

Perform standard CRUD operations via RESTful URIs - Attempt 1

A regular web browser is not suitable for testing our RESTful calls as we also need to be able to enter a client's username and password via a pre-emptive BASIC protocol which is not supported by a regular browser. To this end we will use a RESTful webservices client to test the web-services exposure of our Stadium object. Note that as our extension now has a web services nature, the default "welcome to my extension" message will no longer be returned from http://localhost:9001/cuppywstrail. In fact, you will get a 404 error saying "The requested resource (/cuppywstrail/) is not available.".
  1. Start hybris
  2. Start a RESTful Client
    1. Go to http://code.google.com/p/rest-client/downloads/list and download the REST Client
    2. Download the latest RESTClient GUI release
    3. Run the RESTClient and open Authentication tab, set the Authentication Mode to Basic and Enter “admin” and “nimda” as credentials
  3. Make a RESTful request to view a list of the Stadium
    1. Type and run the URI request http://localhost:9001/cuppywstrail/rest/stadiums in the RESTful Client
    2. You will (probably) receive a response stating that you are not allowed to view this resource

      We will address this issue now.

Modify the RESTful access rights

As discussed in WebService API - Security Architecture users must be a member of the webservicegroup to be able to access resource via REST which is not done by default.
To verify that this user group is set up for you:
  • Open the hMC and see if the usergroup webservicegroup is listed; if not:
    • Create the webservicegroup:
    • Add the user group AdminGroup to the user group webservicegroup:

Perform standard CRUD operations via RESTful URIs - Attempt 2

  1. With a new user group webservicegroup defined as described in WebService API - Security Architecture and the admingroup added to it, our RESTful request with user name admin should now succeed.

    The request returns an XML representation of the Stadiums that are currently in the system.
    <?xml version="1.0" encoding="UTF-8"?>
        <stadium code="Wembley" pk="8796093065099" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley"/>
        <stadium code="Allianz" pk="8796093097867" uri="http://localhost:9001/cuppytrail/rest/stadiums/Allianz"/>
    </stadiums>
  2. Enter the http://localhost:9001/cuppywstrail/rest/stadiums/Wembley to obtain an XML representation of the Wembley Stadium.
    <?xml version="1.0" encoding="UTF-8"?>
    <stadium code="Wembley" pk="8796093065099" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley"
        <comments/>
        <creationtime>2010-11-08T16:30:40+01:00</creationtime>
        <modifiedtime>2010-11-08T16:30:40+01:00</modifiedtime>
        <capacity>123456</capacity>
        <matches/>
        <stadiumType>openair</stadiumType>
    </stadium>
  3. Add some matches to Wembley Stadium in the hMC.
  4. Rerun the query http://localhost:9001/cuppytrail/rest/stadiums/Wembley and you will see the matches you just added.
    <?xml version="1.0" encoding="UTF-8"?>
    <stadium code="Wembley" pk="8796093065099" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley"
        <comments/>
        <creationtime>2010-11-08T16:30:40+01:00</creationtime>
        <modifiedtime>2010-11-10T13:00:40+01:00</modifiedtime>
        <capacity>123456</capacity>
        <matches>
            <match id="1" pk="8796093055137" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley/matchs/8796093055137">
                <matchday>0</matchday>
            </match>
            <match id="4" pk="8796093153441" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley/matchs/8796093153441">
                <matchday>0</matchday>
            </match>
        </matches>
        <stadiumType>openair</stadiumType>
    </stadium>
  5. Notice that the URI attributes in the XML are also URIs pointing to resources. This is a standard RESTful practice in which RESTful responses may contain URIs that in turn can be interrogated.
    Tip
    You may have noticed that responses are by default in XML format. hybris optionally accepts and sends responses in JSON format. To change the default, all you have to do is to set the headers for the request and response:
    Header Entry Value Result
    Accept application/xml Response is sent in XML format
    Accept application/json Response is sent in JSON format
    Content-type application/xml Body in request is expected to be in XML format
    Content-type application/json Body in request is expected to be in JSON format

Modify a Stadium via REST

We will now send a RESTful PUT request to modify the capacity of the wembley stadium.

Custom DTOs and Custom Resources

Earlier we wrote code in your own extension that references the DTOs and Resource generated in the Platform.  Default DTO and Resource implementations may be customized by extending the respective classes.  See Customizing Resources and DTOs for a discussion on how to do this.

Triggering Commands via REST

In addition to performing CRUD on Data via REST, hybris allows you to easily create commands that can then be triggered via RESTful calls. See REST Commands Tutorial for a discussion.

Summary

In this step you should have learned
  • what classes are generated for supporting RESTful CRUD operations on your Data Entities
  • what the webservice_nature target is and why it is needed
  • how to perform RESTful CRUD operations on your Data Entities
  • how to extend DTOs and Resources
  • how to write virtual DTOs

Java : Connecting to an HTTP Web Service from VBA Excel via a Proxy Server

Though MSDN suggests using stubs generated from the WSDL by MS Soap Toolkit for connecting to an HTTP Web Service from within VBA Excel, but it might not work as you would like it to, especially for a SOA-compliant web service and particularly in the cases where you need to access the service via a Proxy Server.

I have used the SOAP Connector called 'httpConnector30' successfully to connect to an HTTP Web Service without any issues. This connector is a part of the Microsoft SOAP Library named MSSOAPLib30 and you got to make sure that this library is referenced in your Excel installation. If it's not already there in your excel, just add the corresponding DLL and you're done.

Using httpConnector30 is different from consuming a Web Service by creating the stubs using MS Soap Toolkit. 'httpConnector30' requires you to specify the actual Web Service URL whereas the toolkit asks you the WSDL url and creates stubs accordingly, which you use in your VBA code. I personally think using 'httpConnector30' is easier and more straightforward if you have the service url.

Before we jump on to the code listed below, let's understand what all the code does broadly:-

    Instantiating the SOAP Connector
    Setting up the Proxy Server and Port (if access needed via Proxy)
    Setting up the Web Service URL (not WSDL url)
    Setting up Timeout period for the service call
    Setting up the SOAP Action i.e., the actual method to be called
    Beginning SOAP Message and getting connector's Input Stream
    Building up the SOAP Request (as per your Web Service definition)
    Sending the SOAP Message (this is where the service call is made)
    Initializing the SOAP Reader and reading the SOAP Response

Note: in the below code I have not shown the exception handling blocks, which you should include to grab and handle the potential errors gracefully. For example: you should first check the 'connector' as 'Not Nothing' before trying to load the 'reader' with connector's output stream.

Additionally, I've assumed that the first node (except the generic envelope and body) of the SOAP Response is actually a List and hence I've put a loop to iterate through it. 'Set response = reader.RPCResult.childNodes' actually sets the 'response' to the first node of the SOAP Response as read from the reader (which itself is loaded with the connector's output stream).

Just to make your service consumption code robust and independent of the Response Structure changes (like addition of new nodes and/or reordering of nodes), in your client code, you should iterate through all the SOAP Response nodes and compare the current node name with your Service Response node names (you can get them in the service WSDL) and subsequently handle the particular node, say inside an if-block. This will make sure that your code doesn't fail abruptly in case Service Response Structure changes. For example: it will avoid any code failure say because you had written it assuming the first node in the response was a List and let's say the service response structure changes make it the second node in the response - maybe because the service provider needed to add another field in the response and also wished to make that the first field. I know the service provide will certainly let the client developers know about the changes, but if you make your code flexible to such possible changes, nothing like it... right?


Public Sub HTTPConnectivityTest()
 
   'Instantiating the SOAP Connector
   Dim connector As New MSSOAPLib30.HttpConnector30
 
   'Setting up the Proxy Server and Port
   connector.Property("ProxyServer") = "fully-qualified-proxy-server-or-IPAddress:Port"

 
   'Setting up the Web Service URL
   connector.Property("EndPointURL") = "http://web-service-server:port/webservices/SampleService.v1"
 
   'Setting up Timeout period for the service call
   connector.Property("Timeout") = 2000 '2 minutes
 
   'Setting up the SOAP Action i.e., the actual method to be called
   connector.Property("SoapAction") = "urn:getSampleData"
 
   'Beginning SOAP Message
   connector.BeginMessage
 
   'Initializing SOAP Serializer with connector's input stream
   Dim writer As New MSSOAPLib30.SoapSerializer30
   writer.Init connector.InputStream

   'Building the SOAP Request - envelope and body
   writer.startEnvelope              ' <SOAP-ENV:Envelope>
   writer.startBody                  ' <SOAP-ENV:Body>

   'Populating the SOAP Request with actual input parameters
   writer.startElement "SampleServiceRequest", "service namespace", , "s3"   ' <SampleServiceRequest>
 
   writer.startElement "inputParam1"   ' <inputParam1>
   writer.writeString "param1 value"    ' value of inputParam1
   writer.endElement                 ' </inputParam1>

   writer.startElement "inputParam2"   ' <inputParam2>
   writer.writeString "param2 value"        ' value of inputParam2
   writer.endElement                 ' </inputParam2>

   writer.startElement "inputParam3"   ' <inputParam3>
   writer.writeString "param3 value"        ' value of inputParam3
   writer.endElement                 ' </inputParam3>

   'Populating list-type parameter
   writer.startElement "paramList"   ' <paramList>

    'Adding node #1 to the list-type param
    writer.startElement "paramListNode"    ' <paramListNode>
     writer.startElement "nodeParam1"          ' <nodeParam1>
      writer.writeString "value1"                    ' value of nodeParam1
     writer.endElement                          ' </nodeParam1>
 
     writer.startElement "nodeParam2"          ' <nodeParam2>
      writer.writeString "value1"                    ' value of nodeParam2
     writer.endElement                          ' </nodeParam2>
    writer.endElement                          ' </paramListNode>

    'Adding node #2 to the list-type param
    writer.startElement "paramListNode"    ' <paramListNode>
     writer.startElement "nodeParam1"          ' <nodeParam1>
      writer.writeString "value2"                    ' value of nodeParam1
     writer.endElement                          ' </nodeParam1>
 
     writer.startElement "nodeParam2"          ' <nodeParam2>
      writer.writeString "value2"                    ' value of nodeParam2
     writer.endElement                          ' </nodeParam2>
    writer.endElement                          ' </paramListNode>
 
   'Population of list-type param ends here
   writer.endElement                          ' </paramList>

   'Finishing the SOAP Request
   writer.endElement                 ' </SampleServiceRequest>
   writer.endBody                    ' </SOAP-ENV:Body>
   writer.endEnvelope                ' </SOAP-ENV:Envelope>
 
   'Sending the SOAP Message (this is where the service call is made)
   connector.EndMessage
 
   'Defining SOAP Reader and initializing it with connector's output stream
   Dim reader As New MSSOAPLib30.SoapReader30
   reader.Load connector.OutputStream
 
   'Parsing the SOAP Response
   Dim response As MSXML2.IXMLDOMNodeList

   'Setting the response to the first node of the SOAP Response
   Set response = reader.RPCResult.childNodes
   Dim node As MSXML2.IXMLDOMNode

   'Iterating through the first node of SOAP Response knowing it is a list
   For Each node In response
    Dim nodeName As String
    Dim nodeValue As String
 
    nodeName = node.nodeName
    nodeValue = node.nodeTypedValue
 
    'Showing the Node Name and Value on Alert Boxes
    MsgBox node.nodeName & ": " & node.nodeTypedValue
   Next node
End Sub