Results 1 to 10 of 10

Thread: How to pass data from JaxRpcPortProxyFactoryBean to SoapHandler(exten GenericHandler)

  1. #1
    Join Date
    Jan 2006
    Posts
    26

    Default How to pass data from JaxRpcPortProxyFactoryBean to SoapHandler(exten GenericHandler)

    Hi,
    Can Anyone help me to explain how to pass addtional data to the SoapHandler, for every webservice invocation made in ProxyFactoryBean.

    FWWSProxyFactoryBean extends JaxRpcPortProxyFactoryBean & registers the FWSoapHandler. I want to pass a HashMap object called "callInfo" (attribute of the FWWSProxyFactoryBean), to the FWSoapHandler for every invocation made.

    Basically the handler needs this hashmap to construct the SoapHeader before invoking the webservice.
    I have passed some values via the config object to the Handler, but the config should contain only the application scoped objects, as I can set the config object only when the Handler is registered for the first time. But I could not figure out how to pass data to the handler, for every webservice invocations.



    public class FWWSProxyFactoryBean extends JaxRpcPortProxyFactoryBean
    {
    ..........

    protected void postProcessJaxRpcService(Service service) {


    HashMap config = getSoapHeaderProperties();
    logger.info("Soap Header Details:" + config);

    QName port = new QName(this.getNamespaceUri(), this.getPortName());
    List list = service.getHandlerRegistry().getHandlerChain(port) ;
    list.add(new HandlerInfo(FWSoapHandler.class, config , null));

    logger.info("Registered JAX-RPC Handler ["
    + FWSoapHandler.class.getName() + "] on port " + port);

    }

    .......

    }



    <bean id="WSProxy"
    class="com.bntaw.avl.fw.wsclient.FWWSProxyFactoryB ean" >
    <property name="serviceInterface">
    <value>${serviceInterface}</value>
    </property>
    <property name="wsdlDocumentUrl">
    <value> ${wsdlDocumentUrl}</value>
    </property>
    <property name="namespaceUri">
    <value>${namespaceUri}</value>
    </property>
    <property name="serviceName">
    <value>${serviceName}</value>
    </property>
    <property name="portName">
    <value>${portName}</value>
    </property>
    <property name="callInfo">
    <map></map>
    </property>

    </bean>


    <bean id="FWWSClient" class="com.bntaw.avl.fw.wsclient.FWWSClient" >
    <property name="service">
    <ref bean="WSProxy"></ref>
    </property>
    </bean>



    Regards
    Agilan

  2. #2
    Join Date
    Jan 2006
    Posts
    26

    Default

    I have passed some values via the config object to the Handler, but the config should contain only the application scoped objects, as I can set the config object only when the Handler is registered for the first time. But I could not figure out how to pass data to the handler, for every webservice invocations.
    I hope I didnt explained clearly, why I cannot use config object to pass callInfo object to the handler. I believe the config object will be initialized only once when the handler gets itself registered. Hence I cannot change the values in the config object for every webservice calls. My problem here is to set a dynamic data (changes for ever webservice calls) in the soap header, Hence I could not use config.
    Can someone pointout how to do it?

  3. #3
    Join Date
    Sep 2004
    Location
    Copenhagen, Denmark
    Posts
    113

    Default

    At this time of writing I don't know how it's possible using the JAX java API.

    I just wanted to tell you that you could use a ThreadLocal to store objects you want to be passed. I know it isn't the most elegant solution but could be a workaround.
    /Claus

  4. #4
    Join Date
    Jan 2006
    Posts
    26

    Default

    Can you throw some light how to pass the object using ThreadLocal.
    What I understand from seeing the documentation of TheadLocal is
    I can create a anonymous class extending ThreadLocal in my ProxyFactoryBean. define a private static object in the ProxyFactoryBean which has to be passed to the Handler. Return that object in the initialvalue() method of the anonymous class. Iam struck up after that. How to get that object in the Handler?
    Would be helpfull if you can show me how to do this.

  5. #5
    Join Date
    Sep 2004
    Location
    Copenhagen, Denmark
    Posts
    113

    Default

    The ThreadLocal is just like a global object for the current thread.

    Spring use this internal to hold e.g. a DataSource that is reused during a transaction etc.

    Using a ThreadLocal doesn't requre to extend a class. You can do it without spring at all.

    Without Spring you can have a singleton class that holds a ThreadLocal attribute.

    Using Spring you can have singleton bean also (is default in spring). And have Spring it inject this bean into the WebService Handler where you do your SOAP header coding.

    I am sure you can find examples how to use ThreadLocal in the spring source code, or from the web.

    I think the ThreadLocal is like a map where you can store whatever objects you want using a key. You just have to remember to clear() to ThreadLocal also to do proper housekeeping.
    Last edited by davsclaus; Jan 26th, 2006 at 03:59 AM.
    /Claus

  6. #6
    Join Date
    Jan 2006
    Posts
    26

    Default

    Thanks a lot for your guidence. It works.
    I have implemented a class which holds a private static instance of ThreadLocal as shown below

    public class MyThreadLocalHolder {

    private static ThreadLocal threadLocal = new ThreadLocal(){
    protected synchronized Object initialValue() {
    return new HashMap();
    }
    };

    public static HashMap getOtherInfo() {
    return (HashMap) threadLocal.get();

    }

    public static void setOtherInfo(HashMap otherInfo){
    threadLocal.set(otherInfo);
    }
    }

    MyProxy will invoke MyThreadLocalHolder.setOtherInfo(map) to set the value &
    MySoapHandler will invoke MyThreadLocalHolder.getOtherInfo() to retrive the value.

    But, I cannt see any method to clear the ThreadLocal after usage.
    I think I should make MyThreadLocalHolder as a singleton as per your suggesion. Will it create a problem this way?
    Last edited by pagilan; Jan 26th, 2006 at 04:53 AM.

  7. #7
    Join Date
    Sep 2004
    Location
    Copenhagen, Denmark
    Posts
    113

    Default

    You clear it by setting the value to null


    // Clear ThreadLocal.
    this.targetInThread.set(null);

    You can see the source from spring
    org.springframework.aop.target.ThreadLocalTargetSo urce


    BTW: I would use the Map interface instead of HashMap, it is commong practice to use interfaces - eg. List instead of ArrayList.
    /Claus

  8. #8
    Join Date
    Sep 2004
    Location
    Copenhagen, Denmark
    Posts
    113

    Default

    You threadLocal is an singleton as it's static.

    Since you use Spring already I would let spring handle the lifecycle. You should implement DisposableBean and then clear the threadlocal in it's destroy method.

    Then Spring does the housekeeping.

    public class MyThreadLocalHolder implements DisposableBean {

    private final static ThreadLocal holder = new ThreadLocal();

    public Map getContext() {
    return holder.get();
    }

    public void setContext(Map context) {
    holder.set(context);
    }

    public void destroy() {
    holder.set(null);
    }

    }

    And home Spring inject this class to MyProxy and MySoapHander in it's xml file.

    You could even create an interface for the context holder, and use this interface from MyProxy and MySoapHandler:

    public interface SoapContext {

    public Map getContext();

    public void setContext(Map context);

    }


    public class MyProxy {

    private SoapContext ctx;

    public void setSoapContext(SoapContext ctx) {
    this.ctx = ctx;
    }

    ...
    }


    And let Spring inject SoapContext to MyProxy class.


    <bean name="MyProxy" ... >
    <property name="soapContext" ref="soapContextBean">
    </>

    <bean name="MySoapHandler" ... >
    <property name="soapContext" ref="soapContextBean">
    </>

    <bean name="soapContextBean" class="...MyThreadLocalSoapContext"/>


    I can't recall if the above spring xml is correct. Haven't use spring for a while.
    Last edited by davsclaus; Jan 26th, 2006 at 09:04 AM.
    /Claus

  9. #9
    Join Date
    Jan 2006
    Posts
    26

    Thumbs down

    Thanks for your reply.
    1. Will use Map instead of HashMap.
    2. "threadLocal is an singleton as it's static."

    I understand I have only one static instance of ThreadLocal, but can I implement a singleton class, so that threadLocal can be invoked in a non-static way. Is it safer than accessing it in a static manner?

    public class MYThreadLocalHolder {

    private static FWThreadLocal objMe = null;
    private static ThreadLocal threadLocal = new ThreadLocal(){
    protected synchronized Object initialValue() {
    return new HashMap();
    }
    };

    private MYThreadLocalHolder (){
    }

    public static MYThreadLocalHolder getInstance(){
    if(objMe==null){
    objMe = new MYThreadLocalHolder();
    }

    return objMe;
    }

    public HashMap getOtherInfo() {
    return (HashMap) threadLocal.get();
    }

    public void setOtherInfo(HashMap otherInfo){
    threadLocal.set(otherInfo);
    }
    }


    3. Making use of spring to inject the HolderClass to the MyProxy and MySoapHandler
    I think this is not possible. MyProxy registers the soaphandler.
    This soaphandler will be invoked by JAXRPC and not via spring. As soon as the call goes to the MYProxy that will be end of the spring's scope. However, MyProxy is configured in spring.

    1. MyProxy has to set the shared object in the MyThreadLocalHolder
    2. MyProxy will invoke the webservice call on the stub
    3. Jaxrpc will invoke the registered soap handler
    4. soap handler will have to get shared object from the MyThreadLocalHolder.

    If I wanted to pass the object from 1 to 4, then I think spring cannot help, unless it comes with a solution to register the soaphandler via spring config file.

    Please advice, whether I make any sense.

    Thanks
    Agilan
    Last edited by pagilan; Jan 26th, 2006 at 07:44 PM.

  10. #10
    Join Date
    Sep 2004
    Location
    Copenhagen, Denmark
    Posts
    113

    Default

    This code is not needed

    private static ThreadLocal threadLocal = new ThreadLocal(){
    protected synchronized Object initialValue() {
    return new HashMap();
    }
    };


    Just use a standard ThreadLocal instead - most people do like this. The initial value is not needed to be set. Just be aware that calling getOtherInfo() can return null.

    private static ThreadLocal threadLocal = new ThreadLocal();


    About 1..4 yes you are right if jaxrpc is invoking your handler and handling the lifecycle of this class. Then Spring can't do anything - except if you use AOP.
    /Claus

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •