Friday, December 26, 2014

What is script connector and how to configure it ???

This post is to understand about "Script connector" and how to configure it. Understanding the necessity of script connector is best explained by explaining about the environment that I have been experienced to.

Without script connector :

I was a part of a team which works  on a framework called "Cordys" and which leverages the usage of its connector capability (able to connect to different systems which are in different platforms like .net, java etc.,) using pre-built connectors like UDDI, SAP Connector etc., As a part of the project we need to integrate with couple of systems and build a process performs a functionality by integrating with those systems. We use UDDI services, SAP Services etc., Hence the development of the process is a lot dependent on the implementation and availability of these services without which we won't be able to finish the implementation of the process.

It would be ideal if we remove this dependency and implement it. There is a way to implement it using a connector built by coe team of cordys which is "Script Connector". Advantages of script connector are 
  • It mimics the response(user configured response) from different system and hence we won't be depending on the availability of the main system instead we create a dummy system which responds like the way main response does.
  • Implementation would be very smooth and doesn't need to depend on any other system.
  • All possible cases can be tested without even bothering the main system.
How to mimic the response  :

There are many ways to replicate the main system by dummy system, current explanation deals with mimic-ing the response by custom logic by retrieving the mimic-ed response from xml store of cordys. 

Initial configuration of script connector : 
In order to have script connector completely configured we need to install the script connector isvp in the environment. My cordys environment is "BOP4.1CU6", hence I would install an ISVP and this isvp can be found out from cordys wiki at this particular link,
https://wiki.cordys.com/display/dsc/Script+Connector
Step 1 : Install the isvp


Step 2 : Go to your organization and try creating a new container. You will be finding a new entry for script connector as shown below,

Step 3:  Go ahead and create the container normally.

Extra configuration to be made :

Here in this section this extra configuration is to be done in order to mimic the response for your service.

Step 4 : Find out what is the web service which you want to mimic. In my case it is "ConversionRate" for which I need to connect to internet and I don't have internet, hence I need to remove this dependency by using script connector.

Step 5 : Edit config.properties file located in the directory 
<<CordysInstalledDirectory>>/coe/scriptconnector/config.properties by adding the below property

*=scripts/all.js  --- This property says any service that you want to mimic can go and refer all.js file. Actual implementation is done at all.js file. I will try to attach all.js file as a comment to the blog post. One must have this file at the location 
<<CordysInstalledDirectory>>/coe/scriptconnector/scripts/.


Step 6 : Have all.js file in the location mentioned above.



Step 7 : According to the implementation in all.js, we must configure our custom response in xml store. The mandatory things we need to make sure are,
  • We must have a folder in xml store as shown below
    • Collection->scriptconnector->all.js
  • Now create a folder with the same name as your "WebServiceOperation" in my case it is "ConversionRate".
  • Now create an Item with any name but which ends with suffix "-Cur" and put any response in that item. In my case it is "success-Cur". All these steps are shown in the below figure,


Step 8 : Attach the interface to be tested to script connector and test it. You would see the same response which you configured in the xml store.



After testing with all possible cases and when we are done with the development from our side we can port these contents to whatever environment you want and connect the interface to the real system instead of script connector. Script connector should be used only in the development environment and not encouraged to be used in any other environments apart from development.     

Tuesday, December 9, 2014

How to implement interceptor for UDDI Service calls

This post describes how to implement interceptor for all external service calls done through UDDI Connector.

Why Interceptor ?

  • End Point not static : You might change the end point for every UDDI call based on some logic. This is a general scenario where in you need to change the end point of all the services for every deployment. This can be achieved by changing every web service's end point by going to external services configuration but this is a tedious task as one needs to do it after every deployment and also to all the web services in the solution. One might think about the effort of changing 10 interfaces having 10 web services in each interface.
  • Defaulting few tags : A Scenario where for every UDDI call there are many tags which are to be defaulted and this should not be taken at process level (BPM level) as it(defaulting) has to be implemented whenever a UDDI service to be called.
  • Tweaking the request : A possible scenario of encrypting/decrypting some or all of the request tags.
  • Tweaking the response : A possible scenario of encrypting/decrypting some or all of the response tags.
  • Audit Log : Auditing every UDDI call.
There might be many more scenarios which might need the concept of Interceptor to be implemented.

How ?
  • We need to write a class which extends Customizer class of UDDIConn.jar. This Customizer class is an abstract class, hence a class which extends this class has to implement all the abstract methods among which OnRequest and OnResponse are also the methods.
  • A Sample scenario in which request and response is logged is shown below,

package better.faster.smarter.development.uddi.interceptor;

import com.eibus.applicationconnector.uddi.AuthenticationDetails;
import com.eibus.applicationconnector.uddi.Customizer;
import com.eibus.applicationconnector.uddi.IHTTPObject;
import com.eibus.applicationconnector.uddi.InterceptorException;
import com.eibus.applicationconnector.uddi.UserInfo;
import com.eibus.util.logger.CordysLogger;
import com.eibus.util.logger.Severity;
import com.eibus.xml.nom.Node;
public class CustomInterceptor extends Customizer {
private static CordysLogger logger = CordysLogger.getCordysLogger(CustomInterceptor.class);@Override
public void initialize(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onHttpRequest(IHTTPObject arg0, UserInfo arg1)
throws InterceptorException {
// TODO Auto-generated method stub
}
@Override
public void onHttpResponse(IHTTPObject arg0, UserInfo arg1)
throws InterceptorException {
// TODO Auto-generated method stub
}
@SuppressWarnings("deprecation")@Override
public void onRequest(int arg0) {
// TODO Auto-generated method stub
logger.log(Severity.WARN, "Writing the request " + Node.writeToString(arg0, true));
}
@SuppressWarnings("deprecation")@Override
public void onResponse(int arg0) {
// TODO Auto-generated method stub
logger.log(Severity.WARN, "Writing the response " + Node.writeToString(arg0, true));
}
@Override
public void onSOAPFault(int arg0) {
// TODO Auto-generated method stub
}
@Override
public AuthenticationDetails getAuthenticationDetails(int arg0, String arg1) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getNewEndpointURL(int arg0, String arg1) {
// TODO Auto-generated method stub
return null;
}
}
  • A Sample scenario of changing the end point is shown below
package com.schneiderelectric.bfoentwebservices.r1;

import com.eibus.applicationconnector.uddi.AuthenticationDetails;
import com.eibus.applicationconnector.uddi.Customizer;
import com.eibus.applicationconnector.uddi.IHTTPObject;
import com.eibus.applicationconnector.uddi.InterceptorException;
import com.eibus.applicationconnector.uddi.UserInfo;
import com.eibus.util.logger.CordysLogger;
import com.eibus.xml.nom.Node;
import com.eibus.xml.xpath.XPath;
public class BFOReqInterceptor extends Customizer
{
  private static final CordysLogger logger = CordysLogger.getCordysLogger(BFOReqInterceptor.class);
  public String getNewEndpointURL(int request, String origURL) {
    int methodNode = XPath.getFirstMatch("//Body/*", null, request);
    String host = Node.getAttribute(methodNode, "SessionURL", null);
    if (host == null) {
      return origURL;
    }
    if (logger.isDebugEnabled())
      logger.debug("Original URL: " + origURL);
    int dblSlashIndex = origURL.indexOf("//");
    int slashIndex = origURL.indexOf("/", dblSlashIndex + 2);
    int colonIndex = origURL.indexOf(":", dblSlashIndex + 2);
    StringBuffer buf = new StringBuffer(origURL);
    buf.replace(dblSlashIndex + 2, colonIndex != -1 ? colonIndex : slashIndex, host);
    if (logger.isDebugEnabled())
      logger.debug("Updated URL: " + buf.toString());
    return buf.toString();
  }
  public AuthenticationDetails getAuthenticationDetails(int paramInt, String paramString) {
    return null;
  }
  public void initialize(int methodImplementation)
  {
  }
  public void onRequest(int request)
  {
  }
  public void onResponse(int response)
  {
  }
  public void onSOAPFault(int soapFault)
  {
  }
  public void onHttpRequest(IHTTPObject arg0, UserInfo arg1)
    throws InterceptorException
  {
  }
  public void onHttpResponse(IHTTPObject arg0, UserInfo arg1)
    throws InterceptorException
  {
  }
}
  • Once the class is developed, we have to make a jar for this package and give this jar as JRE property for UDDI Container.
  • Everything will be useless if you don't change the implementation of the web service for which you need this interceptor to work. Since this is a one time activity, this can be covered in development phase. The changes will go with every deployment.

You need to add the below XML Node to the existing UDDI Service


  <interceptor>
    <class>better.faster.smarter.development.uddi.interceptor.CustomInterceptor</class>
  </interceptor>