Friday, May 31, 2013

Configure OSB Business Service to Call an External HTTPS Service

This writing shows the specific steps on how to configure an OSB business service to make an external HTTPS service call.
1.      Let’s start with the HTTPS site that you need call from OSB. You can retrieve the certificate(s) of the web site with Firefox. Follow the 7 steps (red marked circles on the screen shots) listed in the two screen shots (I used a bank site as an example)
Remember to repeat the 7 steps for each of certificate in the hierarchy in the 2nd screen shot. After these, you should have 3 certificate files. One for the site, one is intermediate CA, and finally a root CA.
Note:
·        You can harvest certificate files from IE or Chrome, the exported file maybe in “.cer” format. Although you can import those “.cer” file into the key store successfully, I was told that it may not work. So you need to make sure your certificate file output in PEM format!
 
 
2.      Import certificates into DemoTrust  (or you designed trust store) store
keytool -import -keystore C:\Oracle\Middleware\wlserver_10.3\server\lib\DemoTrust.jks  -storepass DemoTrustKeyStorePassPhrase -trustcacertificates -file  certX.crt -alias certX 
where “certX.crt” is the certificate file.
Note: 
·        There are two key stores in WSL.
The “trust key store” is for storing external certificates that you “trust”, so WSL can talk to them.
The “identity key store” keeps both public/private key that identifies you, so external parties can identify you.
You can find your key store locations from “Environment->Servers”, click on your server, for example, osb_server1 in the sample screen below:



3.      What if the certificate is a wildcard certificate like *.example.com?
WLS doesn’t support wildcard certificate out of box. For WLS version before 10.3.6, you need to apply a patch. For 10.3.6, you need to follow this link http://docs.oracle.com/cd/E23943_01/web.1111/e13707/ssl.htm#CHDIEIEE
Steps summary: login to WLS console, go to environment, servers, then OSB server, click on configuration, then SSL, then advanced, set custom host verifier, then set the custom verifier class to “weblogic.security.utils.SSLWLSWildcardHostnameVerifier”.
4. If the target service also require WS-name token, then you need to attach the wss-user-token-client-policy to the business service. Check the “security” tab, and make sure you have the matching create “basic.credentials” by default. Or you can use “overrides” to set a different credential, such as “idm.credentials”, technically you can name it anything, you need to make sure “idm.credentials” exits on “em” (under "weblogic domain", your domain name, right click, then select Security, Credentials) console just like “basic.crentials”.


Thursday, May 30, 2013

The "cool" way to do base64 decode with OSB 11.1.1.6

Two years ago, i did a post on how to use proxy java callout to base64 decode with OSB 11.1.1.3 http://yuanmengblog.blogspot.com/2011/04/base64-decoder-for-osb.html.

Now i have 11.1.1.6. Obviously, oracle has moved those jar files around, so you will have to find out where the xerces jar file is if you want to do the same thing in 11.1.1.6.

Well, a colleague brought to my attention something I thought was very cool: using XSLT java call to do the base64 decode. Then you don't need to do the proxy java callout, therefore, saving the trouble of uploading some custom jar file. That sounded very cool, so i decided to give it a shot.

For that we need to resolve two issues. 1. what's the Oracle xslt processor's syntax for java call (it appears to me the XSLT java call syntax varies among different xslt processors). 2. What is the new base64 decoder class in 11.1.1.6. The xslt code below answers both of these questions:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:b64="http://www.oracle.com/XSL/Transform/java/weblogic.apache.xerces.impl.dv.util.Base64"
  >
  <xsl:template match="/">
  <foo>
        <xsl:value-of select="b64:decode('d2xzdXNlcjp3ZWxjb21lMQ==')"/>
    </foo>
  </xsl:template>
</xsl:stylesheet>

plug it into your proxy assignment activity, then you will get an output of
<foo xmlns:b64="http://www.oracle.com/XSL/Transform/java/weblogic.apache.xerces.impl.dv.util.Base64">wlsuser:welcome1</foo>

Keep in mind, directly referencing an undocumented/unsupported oracle class "weblogic.apache.xerces.impl.dv.util.Base64" is a tricky business, proceed at your own risk. currently, this class is inside "com.bea.core.apache_1.3.0.1.jar" under "C:\Oracle\Middleware\Oracle_OSB1\modules" for my 11.1.1.6 install. If oracle decides to change that, then you need to update your xslt as well.

testing on the command line (in my environment):
set classpath=C:\Oracle\Middleware\oracle_common\modules\oracle.xdk_11.1.0\xmlparserv2.jar;c:\Oracle\Middleware\Oracle_OSB1\modules\com.bea.core.apache_1.3.0.1.jar;

first jar is for oraxsl, 2nd jar is for base64 decoding:

java oracle.xml.parser.v2.oraxsl   input.xml     test.xslt

Retrieve and pass around http Authorization header with OSB

It never ceases to amaze me how i stumble on some "new" features with OSB. This time it's to retrieve and pass around http Authorization header with OSB.

I thought it was a long closed chapter that OSB strips off the http basic authentication header before the pipeline is invoked. Well, it's still true, except a colleague showed me there is a trick to make OSB show the http Authorization header!

The trick is to add -Dcom.bea.wli.sb.transports.http.GetHttpAuthorizationHeaderAllowed=true to the OSB start up command. Once you do that, (you still need to check "Get All Headers" on the proxy) you can access the authentication header like regular http user header.
   $inbound/ctx:transport/ctx:request/tp:headers/tp:user-header/@value
The above expression worked for me, because i have only one user-header. i would assume you need to do something like below if you have more than one user-header.
   $inbound/ctx:transport/ctx:request/tp:headers/tp:user-header[@name='Authorization']/@value

In my test case, i'm doing a bit more than just access it on the incoming proxy. I have 3 parts, Proxy1, a biz svc, and Proxy2. I want to pass the authorization header from proxy1 to proxy2 via the biz svc.

The screen below shows Proxy1 uses route to call the biz service, you need to set transport headers for "Outbound Request", check "Pass all Headers through pipeline". That should pass the authorization header on. In my case, i also tested with an additional custom header "aTestHeader" as shown in the screen shot.
One important note, on the biz service, normally it would require enabling "basic" authentication with a "Pass through" service account. However, if you added that magic start up option, then it doesn't matter what the biz service setting is. Because you are passing the authorization header explicitly. Additionally, if you want to see the authorization header in proxy2, you still need to check "pass all headers through pipeline".

On the biz service, that "pass through" service account will help you, if you don't use the magic start up option. In that case, the authorization header will not be explicitly accessible in the proxy, but the biz service will pass it on behind the scene. So if Proxy2 has enabled basic authentication, then the authorization header will be handed over to Proxy2 (behind the scene), so the authentication on proxy2 would succeed.

Wednesday, May 29, 2013

maven/ant/java export osb config jar from the source files

Maven and ant call eclipse plugin "org.eclipse.equinox.launcher" to export the osb config jar file.

Our project default uses OEPE 11.1.1.4. But I have OEPE 11.1.1.6. I had to adjust a few lines to make it work for me. Here is my final result:

<execution>
<id>compileOSB</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target name="makeosbjar">
<path id="library.osb">
<fileset dir="${OSB_HOME}/modules">
<include name="com.bea.common.configfwk_1.6.0.0.jar" />
<include name="com.bea.core.xml.xmlbeans_2.2.0.0_2-5-1.jar" />
</fileset>
<fileset dir="${MW_HOME}/wlserver_10.3/server/lib">
<include name="weblogic.jar" />
</fileset>
<fileset dir="${OSB_HOME}/lib">
<include name="alsb.jar" />
</fileset>
</path>
<java dir="${OEPE_PLUGINS_HOME}/.." jar="${OEPE_PLUGINS_HOME}/org.eclipse.equinox.launcher_1.2.0.v20110502.jar" classpathref="library.osb" fork="true" failonerror="true" maxmemory="768m">
<!--jvmarg line="-d64" /-->
<jvmarg line="-XX:MaxPermSize=256m" />
<arg line="-application com.bea.alsb.core.ConfigExport" />
<arg line="-data ${project.build.directory}/classes" />
<arg line="-configProject MyOSBConfiguration" />
<arg line="-configSubProjects ${osb.config.project}" />
<arg line="-configJar ${project.build.directory}/${project.artifactId}-${project.version}.jar" />
<sysproperty key="weblogic.home" value="${MW_HOME}/wlserver_10.3" />
<sysproperty key="osb.home" value="${OSB_HOME}" />
<sysproperty key="middleware.home" value="${MW_HOME}"/>
</java>
</target>
</configuration>
</execution>

i have highlighted the changes i made. If you have a different OEPE version, you need to find your corresponding jars for these:

    com.bea.common.configfwk
    com.bea.core.xml.xmlbeans
    org.eclipse.equinox.launcher_1.2.0.v20110502.jar

Additionally, I have Java 1.6.0_31. Although it's 64 bit version, it doesn't support "-d64" option. So i took that out. However, the most important parameter i added in is <sysproperty key="middleware.home" value="${MW_HOME}"/>. That resolved that perplexing error message:
...
Caused by: java.lang.NoClassDefFoundError: org/apache/xmlbeans/SchemaTypeLoader
...

==== post note:

Using java directly:
set classpath=C:\Oracle\Middleware\Oracle_OSB1\modules\com.bea.common.configfwk_1.6.0.0.jar;C:\Oracle\Middleware\Oracle_OSB1\modules\com.bea.core.xml.xmlbeans_2.2.0.0_2-5-1.jar;C:\Oracle\Middleware\wlserver_10.3\server\lib\weblogic.jar;C:\Oracle\Middleware\Oracle_OSB1\lib\alsb.jar

set jvmarg=-XX:MaxPermSize=256m -Xmx768m -Dweblogic.home=C:\Oracle\Middleware/wlserver_10.3 -Dosb.home=C:\Oracle\Middleware\Oracle_OSB1 -Dmiddleware.home=C:\Oracle\Middleware

set java_options=-application com.bea.alsb.core.ConfigExport -data D:\proj\osbproj1 -configProject "OSB Configuration" -configSubProjects "OSBProject" -configJar "sbconfig.jar"

java %jvmarg% -jar C:\Oracle\Middleware\oepe11118\plugins\org.eclipse.equinox.launcher_1.2.0.v20110502.jar %java_options%

Here is a full expansion of java command line:

java -XX:MaxPermSize=256m  -Xmx768m  -Dweblogic.home=C:\Oracle\Middleware/wlserver_10.3  -Dosb.home=C:\Oracle\Middleware\Oracle_OSB1  -Dmiddleware.home=C:\Oracle\Middleware  -classpath  C:\Oracle\Middleware\Oracle_OSB1\modules\com.bea.common.configfwk_1.6.0.0.jar;C:\Oracle\Middleware\Oracle_OSB1\modules\com.bea.core.xml.xmlbeans_2.2.0.0_2-5-1.jar;C:\Oracle\Middleware\wlserver_10.3\server\lib\weblogic.jar;C:\Oracle\Middleware\Oracle_OSB1\lib\alsb.jar  -jar  C:\Oracle\Middleware\oepe11118\plugins\org.eclipse.equinox.launcher_1.2.0.v20110502.jar  -application  com.bea.alsb.core.ConfigExport  -data  D:\proj\osbproj1  -configProject  "OSB Configuration"  -configSubProjects  OSBProject  -configJar  sbconfig.jar

keep in mind, "-data  D:\proj\osbproj1" points to source directory of your OSB Configuration and OSB project. In this case, i have an "OSB Configuration" project, and an "OSBProject".

Wednesday, May 22, 2013

Java Web Service Resource Injection Fails on JMS Connection Factory When JMS Server Migrates

Here is the problem:
We have a clustered Weblogic environment. Let's say two managed servers M1 and M2. We have JMS server that needs be migrated among the managed servers. The JMS server is initially targeted to M1.

We have web services running on the cluster. One service publishes messages to the JMS server. This web service uses Java resource injection for the JMS connection factory like:
    @Resource(mappedName="ll.jmsprovider.XAConnectionFactory")
    private ConnectionFactory connectionFactory;

When the service is deployed to the cluster. "connectionFactory" is properly initialized, everything is fine. Even when we shutdown M1, the JMS resource is migrated to M2, the "connectionFactory" still works fine on M2. We can still publish messages.

The problem is when we bring back up M1, and shutdown M2. That's when "connectionFactory" doesn't work anymore. I suspect there might be some configurations on migration policy to make "connectionFactory" work seamlessly when the migration happens. But I don't know how. So my kludge is to recreate the "connectionFactory" on the fly. Here is the entire "hack":

package pubmsg;
import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.SystemException;

@WebService(targetNamespace = "http://pubmsg.org/")
public class msgSender {
    @Resource(mappedName="ll.jmsprovider.XAConnectionFactory")
    private ConnectionFactory connectionFactory;
    @Resource(mappedName="ll.jms.partner.enroll.queue")
    private javax.jms.Queue queue;
      
    public msgSender() {
        super();
    }

    @WebMethod
    @Oneway
    public void sendMessage(String msg) {
        Connection conn = null;
        try {
            try {
                 conn = connectionFactory.createConnection(); // my "hack"
            }
            catch (Exception e) {
                InitialContext ctx = new InitialContext();      
                connectionFactory = (ConnectionFactory) ctx.lookup("ll.jmsprovider.XAConnectionFactory");
                conn = connectionFactory.createConnection();
                queue = (Queue) ctx.lookup("ll.jms.partner.enroll.queue");
            }
   Session session = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
   TextMessage message = session.createTextMessage(msg);
   MessageProducer messageProducer = session.createProducer(queue);
   messageProducer.send(message);
        }
        catch (NamingException e) {}
        catch (JMSException e) {}
        finally {
                if (conn!=null) {
                        try {
                                conn.close();
                        } catch (JMSException e) {}
                }
        }
    }
}

Not the most elegant solution. Oh, well, i need to move on...

Ironically, the purpose of this blog is keep track what i did and how i did it. But it has been several weeks since I worked on it, I already forgot the steps how I created the project :( So I just clicked through JDeveloper try to re-construct the same thing. I believe this is a sequence that can create a java based web service in Jdeveloper (11.1.1.6):

Part I - Ceate a "Web Project"
 1. select project name
 2. select default "serverlet 2.5..."
 3. chose "None" on the "page flow technology" screen
 4. chose no libraries.
 5. select doc root, app name, context root etc.
 6. finish

Part II - add a Java class,
    add the public methods as you need

Part III - add "Web Services->Java Web Service"
   select your java class, from that point on, pretty much follow the screen. That should just work.

====
hmm, i did find another way to create the Java web service: you can start with a generic application, then select "Web Services" for the default project, then "java" is selected by default. However, this process only works for the 1st default project. Once the application is created, and you try to add new project, and you pick "web services", you'll get different options, talking about confused...

Wednesday, May 15, 2013

Use WSLT to set OSB 11g security authorization policy rules

We want to set the proxy service security authorization policy rules using WSLT. This is a biggy. Since it is undocumented feature and not supported by Oracle. I relied on a single post here http://ohnoes-nz.blogspot.com/2012/03/oracle-service-bus-using-wlst-to-secure.html, and I had to do some reverse engineering of Java classes in the OSB jars to sort out the API.

As an occasional user of WLST, I banged my head for a couple of days to make it work with OSB 11.1.1.6. Below is the working version of the script. I left in the comment more calls that can query and set the rules at different levels, feel freel to experiment:

import wlstModule
from com.bea.wli.sb.management.configuration import SessionManagementMBean
from com.bea.wli.sb.management.configuration import ALSBConfigurationMBean
from com.bea.wli.sb.security.management.configuration import ServiceSecurityConfigurationMBean
from com.bea.wli.config import Ref
from com.bea.wli.sb.util import Refs
from java.lang.reflect import Proxy
try:
#############
# execute sentDomainEnv.cmd, then add sb-kernel-impl.jar;com.bea.alsb.security.api.jar to classpath
# to run the script: %wl_home%\common\bin\wlst.cmd (this script file).py
############

# by default, after connect, pwd() shows 'serverConfig:/'
connect("weblogic", "welcome1", "t3://localhost:7001")
########
### locate session bean, then create a new session
#########
domainRuntime() # land in 'domainRuntime:/'
# need domainRuntime(), obtain session management mbean to create a session.
sessionMBean = findService(SessionManagementMBean.NAME,   SessionManagementMBean.TYPE)
print "***SessionMBean is: ", sessionMBean
# create a session
sessionName = String("SecurePaymentService"+Long(System.currentTimeMillis()).toString())
sessionMBean.createSession(sessionName)
print "###session created: ", sessionMBean
########
### create proxy ref
#########
projectName = Refs.makeParentRef("OWSM Demo" + '/')
proxyRef = Refs.makeProxyRef(projectName, "helloBye")
print "***proxyRef: ", proxyRef
proxyReference = proxyRef
########
### find OSB security config bean
#########
serverConfig() # cd('serverConfig:/')
security_mbean_ih = MBeanServerInvocationHandler(mbs, ObjectName("com.bea:Name=%s.%s,Type=%s" % (ServiceSecurityConfigurationMBean.NAME,sessionName, ServiceSecurityConfigurationMBean.TYPE)))
serviceSecurityConfigurationMBean = Proxy.newProxyInstance(ServiceSecurityConfigurationMBean.getClassLoader(),jarray.array([ServiceSecurityConfigurationMBean],java.lang.Class),security_mbean_ih)
print "\r\n###serviceSecurityConfigurationMBean: ", serviceSecurityConfigurationMBean
########
### set up policy holder, and policy scope
#########
policyHolder = serviceSecurityConfigurationMBean.newAccessControlPolicyHolderInstance('XACMLAuthorizer')
print "\r\n=========policyHolder: ", policyHolder

policyStr="Rol(helloRole)"
operation="sayHello"
policyHolder.setPolicyExpression(policyStr)
print "\r\n###policyHolder: ", policyHolder

policyScope = serviceSecurityConfigurationMBean.newOperationMessagePolicyScope(proxyReference, operation)
#policyScope = serviceSecurityConfigurationMBean.newDefaultMessagePolicyScope(proxyReference)
#policyScope = serviceSecurityConfigurationMBean.newProxyPolicyScope(proxyReference)
print "\r\n************************policyScope: ", policyScope

########
### excute security config commands
#########
serviceSecurityConfigurationMBean.setAccessControlPolicy(policyScope, policyHolder)
#serviceSecurityConfigurationMBean.removeAccessControlPolicy(policyScope, policyHolder.getAuthorizationProviderID())

 #px = serviceSecurityConfigurationMBean.getAccessControlPolicy(policyScope, policyHolder.getAuthorizationProviderID())
 #print "###px: ", px
sessionMBean.activateSession(sessionName, "description for session activation")
print "script returns SUCCESS"
except:
    print "Unexpected error: ", sys.exc_info()[0]
    dumpStack()
    raise

The screen shot shows the result the of the execution:

osb/config/sessions directory

I'm working on something that i need to use WSLT to navigate the configuration MBeans on OSB.

Here is what I was doing:

connect("weblogic", "welcome1", "t3://localhost:7001")
custom()
cd('/bea.com')
ls()

Then i see a ton of stuff roll past the screen. They all looked like the sessions that I created while running my test script. They cluttered my screen so I can't see what i was looking for. 

I thought all of these stuff must come from some temp files under the "servers" directly like "AdminServer", "osb_server1" etc, so i blew those directories and restarted the suite, lo and behold, those sessions still show up in the wslt console.

I finally stumbled upon this directory "C:\Oracle\Middleware\user_projects\domains\soa_domain\osb\config\sessions", that's where all the garbage sessions are stored. I just blew them away. Now when i run ls() command, i can find what i was looking for.

Incidentally, i also found out the directories under "sessions" correspond to the OSB session history list when you click on "View Changes" on the top left of sbconsole. If something is changed and saved, but not committed yet, the saved changes are kept in the corresponding session directory.

A few WLST trivia:

1. by default, after you connect("weblogic", "welcome1", "t3://localhost:7001"), your pwd() shows 'serverConfig:/'

2. similarly:
  domainRuntime() - goes to 'domainRuntime:/', it is equivalent to running cd('domainRuntime:/')
  serverRuntime() - goes to 'serverRuntime:/', it is equivalent to running cd('serverRuntime:/')
  serverConfig() - goes to 'serverConfig:/', it is equivalent to running cd('serverConfig:/')
  custom() - goes to 'custom:/', it is equivalent to running cd('custom:/')

Friday, May 10, 2013

Eclipse creates Java Web service client with WSS name token security

This is a combo task. It illustrates an end to end scenario of creating a Web service client based on a WSDL. Then it shows a way to add WSS name token security header, which ironically is different from the previous post http://yuanmengblog.blogspot.com/2013/05/jax-ws-client-call-web-services-with-ws.html

First of all, I use the same fooPS proxy service from OSB (from the previous post). You can find the wsdl from the previous post. I use Eclipse 3.7.1. Here are the steps:

Select JavaEE perspective. Create a new Web Service Client project: File->Other->Web Service Client.

On the next screen, enter your WSDL URL, then move the slide on the left side all the way up.

Then just click finish and let Eclipse does its magic.

When all said and done, Eclipse generates these files:
  • FooBPEL.java - interface, extends Remote
  • FooBPELBindingStub.java - implments FooBPEL and extends Stub
  • FooBPELProxy.java - implements FooBPEL
  • Foobpel_client_ep.java - interface implements Service
  • Foobpel_client_epLocator.java - extends Foobpel_client_ep
I added a server in Eclipse to point to my local Weblogic.


To deploy the new project to the server (I suppose there are better ways to do it): Select Run, Run As, Run on Server, then select the ear to deploy. I only do this once. If I make changes later, i just right click on the server (Tab on the bottom), then select "Publish".

When the deployment is finished, you will get a link http://localhost:7001/WebServiceProject/sampleFooBPELProxy/TestClient.jsp (again, all of these are auto generated, i haven't done a thing yet).

As you can see there is one "process()" method. Try invoke it, it would fail, because there is no security header. For sanity check, you can go to OSB fooPS, remove the WSS security policy, then try to invoke "process()" from the test page again, it should work correctly. Otherwise, you got other problems you need to sort out first before worrying about the security. If it works, then you just succesfully created a Web service client with Eclipse.

Next, I'll show you how I managed to add the security header to the client. In fact, the change is very mimium, but it took me a while to figure it out.

Firstly, i went down a path that did not work out. In the previous post (command line java web service client), the client program relies on casting the "port" into "BindingProvider", then set the security header that way. I just couldn't make it work with the Eclipse generated classes. I couldn't find the equivalent of the "Port" class in this case. Although there is getPort() method in "Foobpel_client_epLocator" class, but I have no way to cast it into the BindingProvider.

Here is what finally made it work: go to FooBPELProxy.java, find "process()" method, make changes as below:
...
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import weblogic.wsee.security.unt.ClientUNTCredentialProvider;
import weblogic.xml.crypto.wss.provider.CredentialProvider;
import weblogic.xml.crypto.wss.WSSecurityContext;
import org.apache.axis.message.SOAPHeaderElement;
import javax.xml.soap.SOAPElement;
...

 public java.lang.String process(java.lang.String input)
   throws java.rmi.RemoteException {
  if (fooBPEL == null)
   _initFooBPELProxy();

  org.apache.axis.client.Stub stub = null;
  try {
   stub = (org.apache.axis.client.Stub) fooBPEL;
   String wsse = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
   String tstr = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
   SOAPHeaderElement security = new SOAPHeaderElement(wsse, "Security");
   SOAPElement usernameToken = security.addChildElement("UsernameToken");
   SOAPElement username = usernameToken.addChildElement("Username");
   username.addTextNode("weblogic");
   SOAPElement pwd = usernameToken.addChildElement("Password");
   pwd.addTextNode("welcome1");
   pwd.setAttribute("Type", tstr);
   stub.setHeader(security);
  } catch (Exception e) {
   System.out.println("exception=" + e.getMessage());
  }
  return fooBPEL.process(input);
 }

That's my hack to make it work. This may not be the way you code for production, it's just a proof of concept. 

JAX WS client call web services with WS-security name token - java command line version

I have an OSB proxy service running on http://localhost:8011/OWSM_Demo/fooPS?wsdl with WS name token security policy enabled. I need to call the service with the proper security header from Java.There are two scenarios: 1. call from command line Java app 2. call from Weblogic web app.

This post covers the command line verion. Web app version will be covered in the next post.

I followed this link: http://middlewaremagic.com/weblogic/?p=18. I first made the sample works as-is. I literrally followed the instructions with variations of my local environment. I have the SOA suite installed locally, i tested adminServer as well as the osb_server1 server. Here is what I did for osb_server1:
  1. In build.xml file, I just changed the weblogic/password, then changed following line for the server:<property name="wls.server.name" value="osb_server1"/> and http://localhost:8011/SecureHelloWorldImpl/SecureHelloWorldService?WSDL
  2. I ran setDomainEnv.cmd under C:\Oracle\Middleware\user_projects\domains\soa_domain\bin
  3. Then I just ran "ant" (the default target is "all").
The default target "all" compiles and deploys a sample web service to the weblogic server (AdminServer or osb_server1). Then generates the client stubs and finally compiles client code and runs the client.

The default build process first creates a web service with WSS name token security policy enabled. Then it generates the client classes based on the WSDL (very import point). Finally, it just invokes the service.This is all good.

Now I need to adapt the same sample to invoke my own OSB fooPS. Keep in mind, if you are only interested in creating a client that can call the OSB proxy fooPS, you only need do "ant client run" (skipping the server tasks).

If you read the build.xml file carefully, you'll see the "client" target is essentially independent of the actual sever implementation. It mostly generates the client classes based on the WSDL. From that I assume I can merely change the WSDL URL and make it work for my own OSB proxy service. Here is how I did it:

I changed WSDL URL in build.xml to point my service http://localhost1:8011/OWSM_Demo/fooPS?wsdl (see end of this post), then I ran "ant client" (I manully cleaned out the "webservicesSecurity_client" directory, you can use ant "clean" task to do it).

Of course, the build would fail because SecureHelloWorldClient.java can't find the original java classes from the original sample. But it did generate the client classes based on the new OSB WSDL, they are:
  • FooBPEL.java - interface
  • FooBPELAsyncHandler.java - I didn't do anything with this one
  • FoobpelClientEp.java - this one extends Service
  • ObjectFactory.java - didn't do anything
  • package-info.java - didn't do anything
  • Process.java - this is based on the only "operation" from the wsdl
  • ProcessResponse.java - operation response based on the WSDL
Now, change SecureHelloWorldClient.java from
  • SecureHelloWorldService service=new SecureHelloWorldService();
  • SecureHelloWorldPortType port=service.getSecureHelloWorldPortTypePort();
 to
  •  FoobpelClientEp service=new FoobpelClientEp();
  •  FooBPEL port=service.getFooBPELPt();
There you go. You can just type in "ant client run". It will invoke your OSB fooPS proxy! If you run into problems, try use TPCMon to debug the issue.

Of couse, you need to change your user/pass accordingly. Also, I didn't bother to change the client package name etc. This is just a proof of concept thing.

The meat part of the client program is to use BindingPort to set the WSS security header.

With the command line success under my belt, i started to migrate the solution to Web app. Of couse, it would be too easy it simply worked. And that's going to be covered in another post (http://yuanmengblog.blogspot.com/2013/05/eclise-creates-java-web-service-client.html).

I can't seem to find a way to add attachment, so here is the wsdl along with the xsd.

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="fooBPEL" targetNamespace="http://xmlns.oracle.com/cis/foo/fooBPEL" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype" xmlns:client="http://xmlns.oracle.com/cis/foo/fooBPEL" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:WL5G3N0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    <plnk:partnerLinkType name="fooBPEL">
        <plnk:role name="fooBPELProvider" portType="client:fooBPEL"/>
    </plnk:partnerLinkType>
<wsp:Policy wsu:Id="wss_username_token_service_policy" xmlns="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<sp:SupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:Policy>
    <wsdl:types>
        <schema xmlns="http://www.w3.org/2001/XMLSchema">
            <import namespace="http://xmlns.oracle.com/cis/foo/fooBPEL" schemaLocation="http://localhost:8011/OWSM_Demo/fooPS?SCHEMA%2FOWSM+Demo%2FfooBPEL"/>
        </schema>
    </wsdl:types>
    <wsdl:message name="fooBPELRequestMessage">
        <wsdl:part name="payload" element="client:process"/>
    </wsdl:message>
    <wsdl:message name="fooBPELResponseMessage">
        <wsdl:part name="payload" element="client:processResponse"/>
    </wsdl:message>
    <wsdl:portType name="fooBPEL">
        <wsdl:operation name="process">
            <wsdl:input message="client:fooBPELRequestMessage"/>
            <wsdl:output message="client:fooBPELResponseMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="fooBPELBinding" type="client:fooBPEL">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
      <wsp:PolicyReference URI="#wss_username_token_service_policy" wsdl:required="false"/>
        <wsdl:operation name="process">
            <soap:operation style="document" soapAction="process"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="foobpel_client_ep">
        <wsdl:port name="fooBPEL_pt" binding="client:fooBPELBinding">
            <soap:address location="http://thinkpad01:8011/OWSM_Demo/fooPS"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

<?xml version="1.0" encoding="UTF-8"?>
<schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://xmlns.oracle.com/cis/foo/fooBPEL" xmlns="http://www.w3.org/2001/XMLSchema">
 <element name="process">
  <complexType>
   <sequence>
    <element name="input" type="string"/>
   </sequence>
  </complexType>
 </element>
 <element name="processResponse">
  <complexType>
   <sequence>
    <element name="result" type="string"/>
   </sequence>
  </complexType>
 </element>
</schema>

Use TCPMon

This is just quick note on TCPMon, an open source tool. Sometimes it can prove invaluable. Yet, I can totally forget where to get it and how to use it. So some quick notes:

1. I think there are multiple versions of this tool. I merely grabbed the oldest one that still works like a charm: http://ws.apache.org/tcpmon/download.cgi (2006, that's ancient!).

2. For the heavy duty TCP monitoring, Wireshark (Ethetreal used to be called) is more powerful. However, TPCMon has its niches:
  • If i remember correctly, Wireshark cannot sniff local traffic (when you want to monitor something from localhost to localhost). But that's where TCPMon shines. It's light weight and can monitor local traffic
  • In fact, TCPMon works a proxy, you direct your TCP traffic to TCPMon, then it forwards to your destination, and you can see the traffic in the TCPMon console.
3. Install and run is like no brainer. Install is just unzip, to run it, it has a batch command tcpmon.bat.

4. Simple use case - I am testing a local web service client, which calls an OSB proxy service on local port 8011 with WS-security header. OSB log shows the security violation, but i can't see what i'm missing in the SOAP header. Here is how i set up TCPMon to check the payload:

On Admin tab, i set
  • Listen port # to 8080 (that's the port TCPMon will monitor).
  • hostname "127.0.0.1"
  • target port# 8011 (TCPMon forwards everything to 8011, which is my OSB port)
  • click add, then you'll see a new tab: port 8080
Let's test it:

My OSB fooPS has a WSDL: http://localhost:8011/OWSM_Demo/fooPS?wsdl

You use http://localhost:8080/OWSM_Demo/fooPS?wsdl to access your fooPS proxy. If you test it with SOAPUI, you'll see your payload show up in the TPCMon console (under "port 8080" tab).

that's all!

 

Thursday, May 9, 2013

Change Derby DB default port 1527 and more

Weblogic comes with Derby database. The default port is 1527. I want to change it to 1528. Ideally, I'd like to set it in weblogic scripts. I couldn't quite do it. Here is my work around, just in case you desperately need to change it.

WL_HOME/common/derby/bin/startNetworkServer.bat (be careful, it's .bat, not the .cmd)

add this at the top of the file (
set DERBY_CMD_LINE_ARGS=-p 1528

You also need to update your domain config/jdbc/*.xml where necessary to 1528 if they references 1527.

Of course, finally, any of your apps that have explicit reference to 1527 also need be updated.

***********
BTW, I tried to change from startWebLogic.cmd

 set DERBY_CMD_LINE_ARGS=-p 1528
 echo DERBY_CMD_LINE_ARGS="%DERBY_CMD_LINE_ARGS%"
 call "%WL_HOME%\common\derby\bin\startNetworkServer.cmd" >"%DOMAIN_HOME%\derby.log" 2>&1

That didn't quite work for me. I scratched my head for long time why the "set" command won't take effect. There must be some other command within the weblogic script set that disabled "set". I couldn't figure out why. Even if "set" command were to work, I still can't figure out how to make the Derby script to see DERBY_CMD_LINE_ARGS setting. Anyone can make it work, i'd like to hear.

5/20/13 - hmm.., just found this link: http://docs.oracle.com/cd/E21764_01/doc.1111/e15866/dev_env.htm#OSBDV1892
Haven't read the details yet, but sounds like interesting...

If you simply getting tired of seeing Derby pops up every time you start weblogic, the best spot to disable it is setDomainEnv.cmd, simply comment out line "set DERBY_FLAG=true". Of course, that's assuming you know what you are doing. If you configured OSB in the domain, by default, it uses Derby for "reporting" service. Turning off Derby will result in jdbc errors when starting Weblogic and OSB. If you don't use OSB reporting, you can simply untarget wlsbjmsrpDataSource. Or you can read this post https://blogs.oracle.com/mneelapu/entry/does_osb_has_any_database_dependency, find the Oracle Db script for OSb reporting, create the tables in Oracle DB, then reconfigure wlsbjmsrpDataSource to point Oracle DB.

Depends on how your installed the OWSM, it may also use Derby. If that's the case, it may not be able to simply turn off derby. That, you may need to re-run RCU or re-install the SOA suite.

If you simply want to mess around with derby DB, here is a good link http://www.vogella.com/articles/ApacheDerby/article.html