Pages

Thursday, August 8, 2013

Logging SOAP Requests in WEF

Some of my projects make extensive use of the web service call builder and I often need to look at the outgoing SOAP requests when a problem crops up. This is easy by turning on logging in the advanced section of the builder, but doing this on every instance of the builder is tedious.


JAX-WS SOAP Handler
I stumbled on this article where Rob Flynn describes a technique to handle SOAP requests from a central point using the bowstreet.serviceCall.jaxwsHandler override. I used this approach to add some log4j logging statements, this way I don't have to go into each builder and tweak the input and redeploy, I can just change the log4j.properties. Unbelievably, a google search shows that there are no other references to this override - not even in IBM's documentation. I have to wonder how many other awesome WEF features lay undocumented (ask me about pageprocessors.properties).

public class SoapHandler extends BaseJaxWsHandler {

    static Logger logger = Logger.getLogger(SoapHandler.class);
    
    /* 
     * Populate the user's identity into the SOAP request.
     */
    public boolean handleOutboundMessage(SOAPMessageContext context) {
        // bail if logging not enabled  
        if (!logger.isInfoEnabled())
            return;
         logMessage(context);
        
        return true;
    }
    
    
    /**
     * Log the SOAP message.
     * @param context
     */
    private void logMessage(SOAPMessageContext context) {

        // bail if logging not enabled  
        if (!logger.isInfoEnabled())
            return;
        
        try {
            HashMap hm = (HashMap) context.get(com.ibm.websphere.webservices.Constants.REQUEST_TRANSPORT_PROPERTIES);
            Set keys = hm.keySet();
            
            logger.info(">> Start SOAP message log");
            logger.info("calling Model=" + getWebappAccess().getModelName());
            logger.info(this.getEndPointUrl(context));

            for (Object key : keys){
                logger.info("HTTP header -> " + key + "=" + hm.get(key));
            }
            
            logger.info(context.getMessage().getSOAPPart().getEnvelope());
            logger.info(">> End SOAP message log\n");
        } catch (SOAPException e) {
            // we're just logging, not sure we care that an exception is thrown
        }
    }


}

The parent class BaseJaxWsHandler can be found on Rob's entry mentioned above.

Friday, May 31, 2013

Product Codes for IBM Software

In many past instances I've been really confused by the download process for IBM Passport. Searching for the correct download package is like trying to find a needle in a haystack.

This week I stumbled on a page I had been looking for, here is a link to the product codes for WebSphere Portal 8:

http://www-10.lotus.com/ldd/portalwiki.nsf/xpDocViewer.xsp?lookupName=IBM WebSphere Portal 8 Product Documentation#action=openDocument&res_title=Electronic_images_wp8&content=pdcontent

Tuesday, April 30, 2013

Using the Localized Resource Builder

Last week I had to use the localized resource builder for localizing an application for one of my clients. After searching a while I did find an article about the topic, and although it didn't meet my needs, it did point me in the right direction.

Localize with the Data Page Builder
Here's the scenario - I have a custom HTML page that has descriptive text to be localized. This is easily accomplished by adding a second data page builder (the first is for the data on the page) that points to the variable created by the localized resource builder.

Here's the HTML I used for page1:
<html>
    <head><title>Default Test Page</title></head>
    <body>
            <div name="contact">
              <span name="name_label"/>
              <span name="name"></span>
<br>
              <span name="phone_label"/>
              <span name="phone"></span>
            </div>
            
            <span name="btn"/>
    </body>
</html>

and here's the default resource bundle:
button_label=click me
phone_label=Phone number:
name_label=Name:
I create a data page builder and point to the variable Variables/LocaleData created by the local resource builder:


When I run the model I get this output:

To test for French language I add a new resource bundle:
button_label=clique moi
phone_label=Numero de telephone:
name_label=Nom:

and change the language to fr:
resulting in this output:

Monday, April 1, 2013

Deploying WARs With a Script

I've wanted to figure this out for a long time and yesterday I finally put together a script that updates a WAR to WebSphere. I have WebSphere Portal running locally on my development box and running the following command will use wsadmin to update a freshly built WAR to the server:

sudo /opt/IBM/WPS8/WebSphere/wp_profile/bin/wsadmin.sh -conntype SOAP -user wpsadmin -password wpsadmin -c "\$AdminApp update POC_WS_war app {-operation update -contents /home/dsixe/WEF/POC_WS.war}"

It took me a while to find out why my script wasn't working, the $AdminApp command requires a \ prefix on non-windows platforms. I initially thought that somebody else would have published a clear example of how to deploy with a script, but I just couldn't find one with repeated google searches (at least none that had the \ prefix).

Monday, December 31, 2012

Documenting WEF Models

Web Experience Factory is a pretty good tool for rapid development, but its designer lacks automated documentation that can be used to explain an application to a new developer. Models can get extremely complicated, especially when they're assembled by developers who are just starting to use the tool. This article describes how graphs can be generated using eclipse.

Using an Eclipse Plugin to Generate Graphs
I've worked with projects that, in some cases, imported dozens of other models, making it quite challenging to follow a sequence of events. About a year ago I had the idea of generating a graph showing how models are imported into each other, but quickly got lost in the details of graphing within eclipse.
I recently stumbled on an open source application named Graphviz, and when I saw the simplicity of using a DOT file to describe a graph, I was able to quickly develop a plugin to inspect a WEF model and produce a graph of it.

An easy candidate for a graph is tracing how models import other models. The plugin does this by recursively traversing the import builders in each model, producing a graph similar to this example.


Once I figured that out, I was able to add some more to the plugin, producing a graph of service consumer operation calls like the one below. This graph indicates that model_4 contains an action list builder named alTest that invokes the doSomeOperation operation exposed by the service consumer builder named svcConsumer.

The graph of action list calls (builders which invoke action lists) is very similar to the one above, except the target node is an action list instead of a service operation.
After the plugin is installed by following these instructions, you will see the following submenu when right clicking on a model.


Just select the graph you wish to generate and it will appear in an eclipse browser window. Although I developed this tool for my own use, I'm making it available free of charge to anyone.

If the tool doesn't work for you, then please leave me a message on this blog (or email me).


References: Download plugin from http://www.dsixe.com/eclipse

Tuesday, December 4, 2012

Using com.bowstreet.builders.webapp.api.Method

I've been writing some more custom builders recently and had a hard time figuring out how to generate a method with arguments.

Below is an example:

        Method method = new Method(builderCall, genContext);
        method.setName("myMethod");
        IXml args = null;
        
        try {
           args = XmlUtil.parseXml("<top><Argument><Name>msgValue</Name><Type>String</Type></Argument></top>");
        } catch (IOException e) {
           e.printStackTrace();
        }
        
        method.setArguments(args);
        StringBuffer sb = new StringBuffer("{ \n");
        sb.append("    webAppAccess.getVariables().getVariable(\"myVar\").setValue(msgValue); \n");
        sb.append("}");
        method.setBody(sb.toString());
        method.invokeBuilder();

and here's the code added to the model on regen:

/**
 * Generated Method [myMethod]
 */
public void myMethod(WebAppAccess webAppAccess, String msgValue)
{ 
    webAppAccess.getVariables().getVariable("myVar").setValue(msgValue); 
}
I figured out the magic XML for method.setArguments() by looking at the model XML for a standard method builder.

Wednesday, November 28, 2012

WEF Profiling Explained

Profiling is a frequently misunderstood concept in web experience factory. This blog entry describes profiling by comparing it to java code, something that more developers are familiar with.

Comparing Profiles to Java Code
Many people struggle with the concept of profiling and profile sets, but it can be closely compared to a conditional statement in java. Suppose that we have a button that needs to be displayed if the application is accessed from an android device. Coding this using java would look something like this (depending on the framework):
if (request.getHeader("User-Agent") == "android"){
   button.visible = true;
}

The same can be accomplished with WEF profiling except we don't have any code to work with, only a button builder with inputs. Ideally, we would want to apply the results of profiling to the builder enable input, setting it to true or false which would effectively replicate what the java code above does.

Think of a profile set as a collection of profiles and the selection of a given profile is the result of a conditional statement. That conditional statement is controlled by a selection handler. Let's look at the code above again from this perspective
if (profileset.selectionHandler.result == "android"){
   button.enable = true;
}

The profile set selection handler is the engine that controls which profile is selected. In this particular case, we're using the mobile selection handler which contains logic that looks at the HTTP request user agent header to determine which profile is selected. Moving one step further, the selection handler doesn't really return a value like "android" per se, it chooses a profile.

Suppose we not only want to control the visibility of a button, but we also want to execute a call to a service provider operation when the application is accessed from an android device. In java, we would add some logic
if (profileset.selectionHandler.profile.name == "android"){
   button.enable = true;
   invokeSomeOperation();
}

For the sake of making this explanation clearer, let's also add some code to handle iPhones as well as a handler for the default case
if (profileset.selectionHandler.profile.name == "android"){
   button.enable = true;
   invokeSomeOperation();
}
else if (profileset.selectionHandler.profile.name == "iphone"){
   button.enable = false;
   invokeSomeOperationIPhone();
}
else{
   button.enable = false;
   // do nothing
}

That all seems very obvious if we were using java, but how is it implemented in WEF using profiling?


Here is the detailed profile entry for the button


Similarly, the action list is profiled



and below is the detailed profile entry


Only one profile in any profile set can be active at one time, and profiling is applied when the user session is first initiated. It is not possible to use two different profiles from the same profile set or switch profiles in the same session.