Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

JWT Databinding

Revision as of 10:59, 15 May 2008 by Mickael.istria.openwide.fr (Talk | contribs) (Concrete issues, remarks)

Aim

The aim of databinding is to provide to JWT the ability to:

  • Deal with orchestration
  • Deal with complex types
  • Deal with type checking
  • To be continued

Thoughts

  • Is a workflow action equivalent to a (mathematical) function? That means, is it a component that takes some input, and computes some output?
  • We need to be able to know the context (with different scopes?) for any entry of action to make the binding.
  • We need to be able to introspect the action to get input and output types. It is easy with WSDL and Java.
  • We need a structured databinding to deal with complex types (classes, records, ...). What we specially require is the ability to browse the context and the variables
    • XPath
    • Expression Language
    • OCL (for EMF models)
    • Anything else?
  • We don't need to be able to evaluate complex (mathematical) expressions. Smart dereferencing is what we are looking for. However, it could be interesting to statically evaluate the type of guard conditions. (check whether a comparison is valid...). It could also facilitate the transformation of boolean expressions.
  • We wouldn't like to use BPEL, however we need something that can easily ve transformed into BPEL.
  • It could be good to be able to do static type checking one a binding.
    • May be difficult since the same data type is not the same programmatic type (eg: String for Java, xs:string for XML...)
    • XPath may not be very helpful for this task
  • Iterations may be problematic to define a context. Should we be only able to bind on the latest result of an iterated action, or should we be able to bind with the result of a specific iteration?
  • Is there a bijection between databindings? If yes, it reduces the risk of making a choice.
  • It could be cool to integrate a Talend-like UI for binding:
  • Should action results automatically global variables, or should they stay "under" the action?

Concrete issues, remarks

Here is the list of remarks that we got when trying to write some code related to web services databinding.

  • Should we really generate a SOAP Request from a WSDL, or just introspect the WSDL enough to know types
  • Where should appear the SOAP Request => Web Service Action in JWT or generated from a transformation from JWT to ...
  • javax.xml.soap and java.wsdl are not really fun to use
  • Could we use an ecore model for WSDL and SOAP?
  • How to make something that works with SOAP, but whom architecture would also fit to REST

M1 : Identify problems

What is necessary to call a web service?

  • WSDL location
  • operation name
  • arguments << this is databinding

From here, we can get the endpoint and the name and types of operation arguments by introspecting the WSDL (not easy). Then we are able to create the request message.

We currently have a SAAJ implementation that is only able to build a SOAP request from a WSDL describing a "WorkflowService", for the method listUserActivities (or any method that arguments are called arg0 arg1 or arg2).

Main improvement would be to introspect the WSDL file to check the signature of an operation and to generate a request that match the name and the number of the arguments.

How to pass the arguments ?

  • method 1 (current): pass an array containing all the arguments. This way, we create the message, and each time we have to put an argument, we put the next item from the list.

The problem is that currently, we are only able to pass "simple" types, but not structured ones. This is not easy to solve since a WSDL can contains sone xsd:schema & co, that are not easy to manipulate with Java.

This method also implies that there is no real type checking, since everything is passed as strings.

package javasandboxplugin;
 
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.RandomAccessFile;
 
import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPMessage;
 
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
 
/**
 * Generated code for the test suite <b>TestSoap</b> located at
 * <i>/javaSandboxPlugin/src/TestSoap.testsuite</i>.
 * 
 * @see http://java.sun.com/javaee/5/docs/tutorial/doc/bnbhg.html
 */
public class TestSoap extends TestCase {
 
	private int currentPrefix = 1;
 
	private int currentArg = 0;
	private Object [] arguments = null;
 
	private String getNextArgAsString() {
		Object res = arguments[currentArg];
		currentArg++;
		return res.toString();
	}
 
	private String getPrefix() {
		return "ns" + currentPrefix;
	}
 
	/**
	 * Constructor for TestSoap.
	 * 
	 * @param name
	 */
	public TestSoap(String name) {
		super(name);
	}
 
	/**
	 * Returns the JUnit test suite that implements the <b>TestSoap</b>
	 * definition.
	 */
	public static Test suite() {
		TestSuite testSoap = new TestSuite(TestSoap.class);
		return testSoap;
	}
 
	/**
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
	}
 
	/**
	 * @see junit.framework.TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {
	}
 
	public void testSoap() throws WSDLException, SOAPException, IOException {
 
		String endpoint = "http://localhost:8086/BonitaScaService";
		String wsdlURI = endpoint + "?wsdl";
		String methodName = "listUserActivities";
		File outputFile = File.createTempFile("test", "test");
 
		SOAPMessage message = generateRequestSkeletton(wsdlURI, methodName, "true", "true", "bsoa");
		message.writeTo(new PrintStream(outputFile));
		String line;
		RandomAccessFile readableFile = new RandomAccessFile(outputFile, "r");
		while ((line = readableFile.readLine()) != null)
			System.err.println(line);
		readableFile.close();
		outputFile.delete();
 
		System.err.println();
		SOAPMessage res = SOAPConnectionFactory.newInstance().createConnection().call(message, "http://localhost:8086/BonitaScaService");
		res.writeTo(new PrintStream(System.err));
		System.err.println();
	}
 
	/**
	 * @param wsdlURI
	 * @param methodName
	 * @return 
	 * @throws WSDLException
	 * @throws SOAPException
	 * @throws IOException
	 */
	private SOAPMessage generateRequestSkeletton(String wsdlURI, String methodName, Object ... args)
			throws WSDLException, SOAPException, IOException {
		this.arguments = args;
		this.currentArg = 0;
 
		WSDLFactory wsdlFactory = WSDLFactory.newInstance();
		WSDLReader wsdlReader = wsdlFactory.newWSDLReader();
 
		wsdlReader.setFeature("javax.wsdl.verbose",false);
		wsdlReader.setFeature("javax.wsdl.importDocuments",true);
 
		Definition definition = wsdlReader.readWSDL(wsdlURI);
		if (definition == null)
		{
		System.err.println("definition element is null");
		System.exit(1);
		}
 
		/**
		 * Header & footer
		 */
		MessageFactory messageFactory = MessageFactory.newInstance();
		SOAPMessage message = messageFactory.createMessage();
		message.getSOAPHeader().detachNode();
		SOAPBody body = message.getSOAPBody();
		/**
		 * Method
		 */
		QName bodyName = new QName(definition.getTargetNamespace(), methodName, getPrefix());
		SOAPBodyElement bodyElement = body.addBodyElement(bodyName);
		bodyElement.addNamespaceDeclaration("ns1", definition.getTargetNamespace());
 
		/**
		 * Args
		 */
		printArgs(definition, methodName, bodyElement);
 
		return message;
 
	}
 
	private void printArgs(Definition definition, String methodName,
			SOAPBodyElement bodyElement) throws SOAPException {
		/*
		 * Hack!!!
		 */
 
		/**
		 * 1. récupérer args 
		 * 2. for arg:args 
		 *   a. Regarder type
		 *      Si type natif => Go
		 *      sinon Trouver type dans les complexTypes
		 */
 
		SOAPFactory soapFactory = SOAPFactory.newInstance();
		SOAPElement arg0 = bodyElement.addChildElement(soapFactory
				.createElement(new QName(definition.getTargetNamespace(),
						"arg0", "ns1")));
		arg0.setValue(getNextArgAsString());
		SOAPElement arg1 = bodyElement.addChildElement(soapFactory
				.createElement(new QName(definition.getTargetNamespace(),
						"arg1", "ns1")));
		arg1.setValue(getNextArgAsString());
		SOAPElement arg2 = bodyElement.addChildElement(soapFactory
				.createElement(new QName(definition.getTargetNamespace(),
						"arg2", "ns1")));
		arg2.setValue(getNextArgAsString());
 
	}
 
}

Web service action

JWT contains a "Web service Application", that represents a call to a web service. This item inherits from application, that is not an abstract application, but a kind of "Java Agilpro Application". Thus, it would be useful to create an Abstract Application, that would be used to define any concrete application (Java, WS, BPEL, SCA, Human...)

M2 : Runtime

Try Web Service in AgilPro Simulator Try to develop a Bonita Hook and to add the support of Web Service Action in JWT to XPDL transformation, to make it work in Bonita.

Back to the top