workarea SOAP header cause the SOAPFaultException

By W.ZH Dec 2014

Issue:

When I was working on a project about the WS, my client jar always get this error:

Get Eligibility failed. Severity level is 5. Msg=SOAPFaultException – FaultCode [{http://schemas.xmlsoap.org/soap/envelope/}Server] FaultString [15
] FaultActor [null] Detail [<detail><bea_fault:stacktrace xmlns:bea_fault=”http://www.bea.com/servers/wls70/webservice/fault/1.0.0″>java.lang.ArrayIndexOutOfBoundsException: 15
at com.sun.beans.ObjectHandler.dequeueResult(ObjectHandler.java:139)
at java.beans.XMLDecoder.readObject(XMLDecoder.java:201)
at weblogic.wsee.workarea.WorkContextXmlInputAdapter.readUTF(WorkContextXmlInputAdapter.java:111)
at weblogic.workarea.spi.WorkContextEntryImpl.readEntry(WorkContextEntryImpl.java:92)
at weblogic.workarea.WorkContextLocalMap.receiveResponse(WorkContextLocalMap.java:226)
at weblogic.workarea.WorkContextMapImpl.receiveResponse(WorkContextMapImpl.java:182)
at weblogic.wsee.workarea.WorkAreaClientHandler.handleResponse(WorkAreaClientHandler.java:49)
at weblogic.wsee.handler.HandlerIterator.handleResponse(HandlerIterator.java:287)
at weblogic.wsee.handler.HandlerIterator.handleResponse(HandlerIterator.java:271)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.handleResponse(ClientDispatcher.java:213)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.dispatch(ClientDispatcher.java:150)
at weblogic.wsee.ws.WsStub.invoke(WsStub.java:87)
at weblogic.wsee.jaxrpc.StubImpl._invoke(StubImpl.java:341)

When I look at the SOAP XML. found this in the header:

<work:WorkContext xmlns:wsu=”http://schemas.xmlsoap.org/ws/2002/07/utility&#8221;

                      xmlns:work=”http://bea.com/2004/06/soap/workarea/”&gt;

     <java class=”java.beans.XMLDecoder”>

      <string>**************</string>

      <int>214</int>

      <string>weblogic.workarea.StringWorkContext</string>

      <string>1.4.1.18</string>

      <string>oracle.dms.context.internal.wls.WLSContextFamily</string>

      <int>335</int>

      <string>weblogic.workarea.SerializableWorkContext</string>

      <int>356</int>

      <array class=”byte” length=”356″>

       <void index=”0″>

       ……………………………………..

      <boolean>false</boolean>

      <string/>

     </java>

    </work:WorkContext>

 

Reason:

As my jar client is legacy code, so it in fact can not read this extra header properly, so it will get error.

Solution:

Use this flag at your setDomainEnv.sh to change java flag for this extra header:

-Dweblogic.wsee.workarea.skipWorkAreaHeader=true

after restart server. it will be fine

Advertisements

local class incompatible: stream classdesc serialVersionUID = -4312319268131871162, local class serialVersionUID = -5312119737527277188

    By W.ZH  Aug 2014

Issue:

When we use some webservice , we get error like this :

java.io.InvalidClassException: com.abc.EmailInfo; local class incompatible: stream classdesc serialVersionUID = -4312319268131871162, local class serialVersionUID = -5312119737527277188

com.abc.EmailInfo is a java object is used in some code.

 

 

Reason:

com.abc.EmailInfo exist in fact in several jar files. each jaf file in fact contain a different version of the  EmailInfo  class, even class source code could lokks like same.

 

What we should do is:

1. find out all the jar files that contain this class file:  j1.jar and j2.jar such as.

2. use serialver to check the serialVersionUID of each class in each jar:

       C:\SVN\….WEB-INF\lib>serialver -classpath jar1.jar com.abc.EmailInfo

        com.abc.EmailInfo:    static final long serialVersionUID = -5312119737527277188L;

    

       C:\SVN\….WEB-INF\lib>serialver -classpath jar2.jar com.abc.EmailInfo

        com.abc.EmailInfo:    static final long serialVersionUID = -4312319268131871162L;

3. now you see the reason of the class with same name of diff version in fact will creat different serialVersionUID

4. so try to unzip one of jar file and then get class to update the other one, suppose the have same code for EmailInfo class, so they can exchange with each other.

5. use this command to update the class in one jar file:

C:\SVN\….WEB-INF\lib>jar uf jar1.jar com\abc\EmailInfo.class

Then you can try to see result.

How to add data to SOAPHeader in the Web Service client code

By W.Zh   Mar 2014

Request

When you create a web service client proxy, after that, you want to insert some data in the SOAP header part, such as some security information, some user related or transaction information etc. how to do that in the WS java client code?

Solution

Use the
SOAPHandler to do this.

1. Create a SOAPandler  class to implement the handleMessage, inside this you can create your own SOAP elements structure and add to the SOAP header part. code is like this.


import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;

import java.util.Set;

import java.util.TreeSet;

import javax.xml.namespace.QName;

import javax.xml.soap.SOAPElement;

import javax.xml.soap.SOAPEnvelope;

import javax.xml.soap.SOAPFactory;

import javax.xml.soap.SOAPHeader;

import javax.xml.soap.SOAPMessage;

import javax.xml.ws.handler.MessageContext;

import javax.xml.ws.handler.soap.SOAPHandler;

import javax.xml.ws.handler.soap.SOAPMessageContext;

public class SOAPHeaderHandler implements SOAPHandler<SOAPMessageContext> {

  

    private static final String CLASS_NAME = “SOAPHeaderHandler”;

  

    public Set<QName> getHeaders() {

        return new TreeSet();

    }

    //<ns1:Security xmlns:ns0=”http://com.test.ws/”&gt;

    //       <ns1:userName>name here</ns0:userName>

    //     </ns1:Security>

    public boolean handleMessage(SOAPMessageContext context) {

        Boolean outboundProperty =

            (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

     

        if (outboundProperty != null && outboundProperty.booleanValue()) {

            SOAPMessage message = context.getMessage();

            try {

                SOAPEnvelope envelope =

                    context.getMessage().getSOAPPart().getEnvelope();

                SOAPHeader header = envelope.getHeader();

                SOAPFactory factory = SOAPFactory.newInstance();

                String prefix = “ns1”;

                String uri = “http://com.test.ws/&#8221;;

                SOAPElement securityElem =

                    factory.createElement(“Security”, prefix, uri);

                SOAPElement nameElem =

                    factory.createElement(“userName”, prefix, uri);

                String na = “Name here”;

                nameElem.addTextNode(na);

                securityElem.addChildElement(nameElem);

                // if no header, add one

                if (header == null) {

                    try {

                        header = envelope.addHeader();

                    } catch (SOAPExceptionImpl se) {

                      se.printStackTrace();

                    }

                }

                header.addChildElement(securityElem);

            } catch (Exception e) {

                e.printStackTrace();

            }

        } else {

            // inbound

        }

        return true;

    }

    public boolean handleFault(SOAPMessageContext context) {

       

        return true;

    }

    public void close(MessageContext context) {

        //

    }

}

2.  Then you can use the Jdev to create a Web server proxy client code. at the client code, after you get the server, you can setup the handler chains before you can the method in your WS.

YourWebservice yourWebservice=
new YourWebservice(new URL(yourWSDLAddress),
new QName(“http://………………&#8221;,
“YourWebservice”));

//add header for SOAP
yourWebservice.setHandlerResolver(new HandlerResolver() {
  public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerList =
new ArrayList<Handler>();
handlerList.add(new SOAPHeaderHandler());
return handlerList;
}

});

3. Please note that
new YourWebservice(new URL(yourWSDLAddress), new QName(“http://………………&#8221;,”YourWebservice”));
is be used to define the dynamic WSDL URL.
 

 

ADF Business Components Service relation to normal WS

By W.Zh Oct 2011

ADF Business Components Service in the fusion dev guide is the web service interface that exposed from a BC Application Module. But BC Service is not a normal web service. It has more features than a normal webservice.

  1. For a normal web service, if you want access from your java code, in Jdev, you can create a static client proxy code call this WS. If you have the BC service, you still can do this way. This means you can invoke BC service like others normal WS in your java application code.
  2. If you have one ADF web application to invoke another BC service remotely, then best way to access the BC Service, is not through the java WS static proxy code to call it. You should use the oracle.jbo.client.svc.ServiceFactory to invoke the BC service. You get more benefit by this way. See the chapter 41 of the “Oracle Fusion Applications Developer’s Guide”.
  3. If you have one SOA composite application, you want to invoke a BC service remotely, you have two choices here for  SOA access the external WS service,  one is called “ADF-BC service”. This one is dedicated for BC service, another one called “Web Service”. Of course, the best way to use the “ADF-BC service”.
  4. By “ADF-BC service” and oracle.jbo.client.svc.ServiceFactory you can invoke the BC service, and you also can access the SDO objects which exposed via this service. So you can change these SDO data, and save to DB. Do not need to call some method in service interface method to do that. You have to refer to fusion dev guide to see how to use this.  In SOA, there are something called “entity variables” in BPEL can use SDO object from partner links (Such as ADB-BC links).

 

Some examples to create BC service and consumed by a SOA application, and entity variables.

 

http://go2kavinkumar.wordpress.com/tag/adf-bc-service/

http://go2kavinkumar.wordpress.com/2011/08/16/invoking-an-adf-bc-service-asynchronously-from-soa-composite-bpel-11g/

http://jianmingli.com/wp/?p=2838

 

 

 

 

How to change configurable values in Oracle Service Bus projects

By W.ZH July 2011

Issue:

You know, in the SOA composite application, when u do the deployment, you can compose a config plan file to dynamically change some data and values in the BPEL projects to meet your server IP/Port and other environment. Does OSB project has similar feature? Such as you have a PS point to a BS, Business Service created from a WSDL which is from a developing server IP and port, so when you go the deploy this OSB project to the production server, how to change this IP and port info?

Solution:

OSB has similar feature called Customization File:  From OSB manage console:

System Administration –>Customization –>

Find & Replace

Create Customization File

Execute Customization File

You can Create a Customization File for your project. It is a XML file, open it and you see many resources can be changed.

You change this file’s data , and then you can Execute your Customization File, then new values will be applied to your project.

This Customization File also can be used in the WLST, when you try to import the OSB project into the OSB server by WLST py file, you can also use a Customization File

to replace your project data and make it imported to OSB server with new settings. I will have another article to introduce the WSLT import OSB project.

 

OWSM For WS Security in Oracle Service Bus

July 2011, By W.ZH

I am going to give you a small example on the WS security in OSB. This is going to be a very good example to let you pick up and to test the OWSM on OSB easily. OWSM is the oracle recommended way to secure your web service in 11g release. I have made all following running in my system.

1. When you extend your domain in Weblogic , you need to select the “OWSM extension for OSB” lib in the domain extension, and this is not removable.

2. You can use java tool key to create a keystore file in the domain’s config folder,
<DOMAIN_HOME>/config/fmwconfig

        keytool -genkey -keyalg RSA -dname "cn=XXX,OU=XXX,O=XXX,L=XX,ST=XX,C=XX,dc=XXX,dc=XXX" -alias orakey -keypass pass1 -keystore default-keystore.jks -storepass pass2 -validity 1064

3. The key store file name we use is the default file name here, it by default setting in the
jps-config.xml
, you can open this file take a look the node of
serviceInstance
:

<serviceInstance name=”keystore” provider=”keystore.provider” location=”./default-keystore.jks”>

 
<description>Default JPS Keystore Service</description>

4. You need to restart your WLS and others to let WLS pickup this keystore file. Start your domain with SOA suite and OSB server.

5. You can go to Fusion Middleware control to set up your key store:

WebLogic Domain menu, select
Security -> Security Provider Configuration.

      1. Expand the Keystore section on the Security Provider Configuration page.
      2. Click Configure.
      3. Check Configure Keystore Management and use the following settings to specify the location of the keystore that contains the certificate and private key, and the signature key and encryption key aliases:
        • Keystore Path: ./default-keystore.jks
        • Password: Enter and confirm the password for the keystore. (pass2)
        • Key Alias: orakey
        • Signature Password: Enter and confirm the password for the signature key.(pass1)
        • Crypt Alias: orakey
        • Crypt Password: Enter and confirm the password for the encryption key.(pass1)
      4. Click OK to save your settings. Restart the Administration server for the domain.

6. Beside that, another way to do this is by
WLST commands to update the credential store:

createCred(map=”oracle.wsm.security”, key=”keystore-csf-key”, user=”owsm”, password=keystore_password, desc=”Keystore key”)

createCred(map=”oracle.wsm.security”, key=”enc-csf-key”, user=”orakey”, password=private_key_password, desc=”Encryption key”)

createCred(map=”oracle.wsm.security”, key=”sign-csf-key”, user=”orakey”, password=private_key_password, desc=”Signing key”)

7. Ok you have set up all these keystrore ready for tesing the OWSM on OSB.

At OSB side:

  1. Go to your OSB console http://yourIP:7001/sbconsole/, create one project.
  2. Create one Buisiness service from a WS WSDL
  3. Create one Proxy Service by that Business Service.
  4. Ok, you can test your proxy service using the “test console”,
  5. Now it is ready to apply the OWSM Assertions policy to it,
  6. We can add the oracle/wss_username_token_service_policy for testing now
  7. In OSB web Console, Click Resource Browser, click Proxy Services and click on your proxy service to edit the configuration
  8. Navigate to Policies tab
  9. Select OWSM Policy Bindings
  10. Click Add to add an OWSM Policy
  11. Select OWSM Policy dialog is displayed. Select oracle/wss_username_token_service_policy. Click Submit
  12. Then Update to make policy run. (In the security part double check that set Process WS-Security Header flag to YES (Do not miss this step) )
  13. Ok, you can start test from test console again, you need to supply the username and password for the SOAP header to make the test can work.
  14. So how you can get the user name and password submited in test console?
  15. Create a user in the WLS security realm in EM, you can also do this from the OSB console, eg. user_a/password3,
  16. In EM, go to the domain –credential setting, you will see the map over there for “oracle.wsm.security“, create one more key there for testing user a:

    key: usera_key

    username: user_a

    pass: password3

  17. Ok we can use this key to retrieve the username and pass in the OSB test console to test the WS.
  18. In the test console , you can choose to overide the csf-key values.

    Policy Name  — oracle/wss_username_token_client_policy

    Property — csf-key

    Default Value    —- basic.credentials

    Override Value    —   usera_key

  19. Then when you try to test a WS call, the test console will auto get user_a and pass to compose the WS-Security SOAP header for you and to hit the OSB proxy Service.

All these are concise steps for OWSM ruuning on OSB proxy service. For OSB project you need to commit your change for changing session every time you change it.

There is a chapter in the Oracle® Fusion Middleware Administrator’s Guide for Oracle WebCenter 11g (R4) – 28 Configuring WS-Security for WebCenter Applications and Components , it gives an example that how you can apply the WS-security on the Web Center related service. It in fact is a good example of how to config and apply the OWSM to any WS.

How to add the OWSM to WS server side and client side

By W.ZH July 2011

Oracel Web Service Manager is to add the WS security policy to the  web service, can be add to the ADF BC WS, ADF data control WS, an SOA applications’s WS and also a normal WS, such as and EJB WS. I just  add some my experience here for future easily pick up OWSM.

Server Side:

For a normal WS, there are several ways you can add the WS security plicy to the WS Server Side:

1. Design time, when you design the WS in Jdeveloper, you can right click that WS to config’s policy and it will add some security related annotiona to your WS method signature.

2. Or, after your WS is deployed, you can add the security policy at run time, you can either do from EM fusion middleware control , or from WLS console.

In EM control, find the WS in your domain — select the endpoint and select the policy to attach and de-attach the policy to it.

In console, you can go to deployment– your WS project — ur WS — in its configuration, to select the WS-policies to config its policy.

Client Side:

1. Your client is the JAVA code in Jdeveloper, you can create an WS proxy client in Jdev first, after you have that proxy, you can right click the proxy to change its’ properties and, after you get the dialog for proxy prpoperties, there is one can let u change the client proxy, set it matches with your server side proxy and also change the related java code to input the data to make it can call the WS be secured. Something code like this:

   // set the WS service and security token
SecurityPolicyFeature[] securityFeatures =
new SecurityPolicyFeature[] { new SecurityPolicyFeature(“oracle/wss_username_token_client_policy”) };
myService =
new MYService(new URL(“http://127.0.0.1:7001/MyService?WSDL&#8221;),
myQName);
MyEJBBean myEJBBean =
myService.getMyServicePort(securityFeatures);

Map<String, Object> myReqContext =
((BindingProvider)myEJBBean).getRequestContext();
myReqContext.put(BindingProvider.USERNAME_PROPERTY, “user name”);
myReqContext.put(BindingProvider.PASSWORD_PROPERTY, “password”);

Then you can call the WS like normal proxy code to call the WS server side.

2. Your client is the SOA composite application, such as inside a BPEL process, you have a “invoke” to call the WS proxy outside the BPEL process. You can right click that invoke to config’s WS client policy too, you can refer the dev guide about this part. should not be too hard.