camel-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Florent Legendre (Updated) (JIRA)" <j...@apache.org>
Subject [jira] [Updated] (CAMEL-5112) Erroneous support of Jaxb web services taking serveral Holder arguments
Date Fri, 23 Mar 2012 08:15:26 GMT

     [ https://issues.apache.org/jira/browse/CAMEL-5112?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Florent Legendre updated CAMEL-5112:
------------------------------------

    Description: 
Hi,
*NB*
I ran into a problem while using the camel-soap module. I have created a patched version of
the problematic classes and am totally open for submitting them for review in hope that it
could increase the chance for this bug to be fixed in a near future. 

*The problem*
I have to integrate with a web service with that type of signature (generated from the original
wsdl file with the help of wsimport):

{code}
@WebMethod
@WebResult(name = "Details", targetNamespace = "http://example.com/service.xsd", partName
= "response")
public Details fetchDetails(
        @WebParam(name = "fetchDetails", targetNamespace = "http://example.com/service.xsd",
partName = "fetchDetails")
        Personsearch fetchDetails,
        @WebParam(name = "Session", targetNamespace = "http://example.com/service.xsd", header
= true, mode = WebParam.Mode.INOUT, partName = "Session")
        Holder<Session> session,
        @WebParam(name = "Transaction", targetNamespace = "http://example.com/service.xsd",
header = true, partName = "Transaction")
        Transaction transaction,
        @WebParam(name = "Transactioninfo", targetNamespace = "http://example.com/service.xsd",
header = true, mode = WebParam.Mode.OUT, partName = "Transactioninfo")
        Holder<Transactioninfo> transactionInfo)
        throws FetchDetailsException
    ;
}}
{code}

The call to the web service is set up as documented in the wiki (all this done in the context
of a {{Processor#process(Exchange)}} method)
* Create a bean invocation
* Set the Method object representing the method to be called (fetchDetails in my case) on
the bean invocation
* build the parameters for the method call and set them on the bean invocation.
* Set the bean invocation in the out body of the exchange

This kind of setup leads to incorrect generation of the xml sent to the webservice. The reason
for this is:
* When specifying the method to invoke i have to write {{beanInvocation.setMethod(ServicePortType.class.getMethod(WS_METHOD_NAME,
Personsearch.class, Holder.class, Transaction.class, Holder.class));}}. Note that this method
signature contains two Holder objects.
* When {{ServiceInterfaceStrategy}} goes through {{#analyzeServiceInterface}} it uses the
name of the class object passed in the signature as key in the {{ServiceInterfaceStrategy.inTypeNameToQName}}
Map. 
* Because there are two {{Holder}} instances in the signature it means that only one of the
two QName which are added to the map will be found, as they both rely on the same {{Holder.class}}-based
key
* The problem above occurs when {{ServiceInterfaceStrategy#findQNameForSoapActionOrObject}}
reads from {{ServiceInterfaceStrategy.inTypeNameToQName}}, getting the exact same QName out
of the map for both objects, hence generating erroneous xml (Note that nothing fails, it just
sends rubbish to the webservice)

*A solution*
Files that I "Patched" to get this case to work:
* org.apache.camel.dataformat.soap.name.ElementNameStrategy
* org.apache.camel.dataformat.soap.name.ServiceInterfaceStrategy
* org.apache.camel.dataformat.soap.name.TypeNameStrategy
* org.apache.camel.dataformat.soap.SoapJaxbDataFormat


My solution relies on the following:
* For the end user the "receipe" is still exactly the same with use of BeanInvocation
* I have created a utility class to generate suitable keys for adding/retrieving Holder objects
(see further down).
* I modified the method {{PatchedElementNameStrategy#findQNameForSoapActionOrObject(String
soapAction, Object object)}} to take an object parameter instead of a class. This gives this
method the correct tool (the object, not the class) to produce a key which actually retrieves
the correct QName

All this works fine for me and I would like to submit my patch to the project.
{code}
package org.apache.camel.dataformat.soap.name;

import javax.xml.ws.Holder;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public final class ElementNameStrategyUtils {

    private ElementNameStrategyUtils() {
        // utility class
    }

    /**
     * Generates a suitable key for adding a QName in one of the <code>Map<String,
QName></code> <code>PatchedServiceInterfaceStrategy</code>.
     *
     * @param type
     * @return
     */
    public static String getTypeNameForType(Type type) {
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            StringBuffer typeName = new StringBuffer();
            Class<?> rawTypeAsClass = (Class<?>) parameterizedType.getRawType();
            typeName.append(rawTypeAsClass.getName());
            for (int i = 0; i < parameterizedType.getActualTypeArguments().length; i++)
{
                Type actualTypeArg = parameterizedType.getActualTypeArguments()[i];
                typeName.append("-");
                typeName.append(getTypeNameForType(actualTypeArg));
            }
            return typeName.toString();
        } else {
            Class<?> typeAsClass = (Class<?>) type;
            return typeAsClass.getName();
        }
    }

    /**
     * Generates a suitable key for retrieving a QName from one of the <code>Map<String,
QName></code> <code>PatchedServiceInterfaceStrategy</code>.
     *
     * @param object
     * @return
     */
    public static String getTypeNameForObject(Object object) {
        if (object instanceof Holder) {
            Holder holder = (Holder) object;
            StringBuffer typeName = new StringBuffer();
            typeName.append(holder.getClass().getName());
            if (holder.value != null) {
                typeName.append("-");
                typeName.append(getTypeNameForObject(holder.value));
            }
            return typeName.toString();
        } else {
            return object.getClass().getName();
        }
    }


}
{code}

  was:
Hi,
*NB*
I ran into a problem while using the camel-soap module. I have created a patched version of
the problematic classes and am totally open for submitting them for review in hope that it
could increase the chance for this bug to be fixed in a near future. 

*The problem*
I have to integrate with a web service with that type of signature (generated from the original
wsdl file with the help of wsimport):

{{code}}
@WebMethod
@WebResult(name = "Details", targetNamespace = "http://example.com/service.xsd", partName
= "response")
public Details fetchDetails(
        @WebParam(name = "fetchDetails", targetNamespace = "http://example.com/service.xsd",
partName = "fetchDetails")
        Personsearch fetchDetails,
        @WebParam(name = "Session", targetNamespace = "http://example.com/service.xsd", header
= true, mode = WebParam.Mode.INOUT, partName = "Session")
        Holder<Session> session,
        @WebParam(name = "Transaction", targetNamespace = "http://example.com/service.xsd",
header = true, partName = "Transaction")
        Transaction transaction,
        @WebParam(name = "Transactioninfo", targetNamespace = "http://example.com/service.xsd",
header = true, mode = WebParam.Mode.OUT, partName = "Transactioninfo")
        Holder<Transactioninfo> transactionInfo)
        throws FetchDetailsException
    ;
}}
{{code}}

The call to the web service is set up as documented in the wiki (all this done in the context
of a {{Processor#process(Exchange)}} method)
* Create a bean invocation
* Set the Method object representing the method to be called (fetchDetails in my case) on
the bean invocation
* build the parameters for the method call and set them on the bean invocation.
* Set the bean invocation in the out body of the exchange

This kind of setup leads to incorrect generation of the xml sent to the webservice. The reason
for this is:
* When specifying the method to invoke i have to write {{beanInvocation.setMethod(ServicePortType.class.getMethod(WS_METHOD_NAME,
Personsearch.class, Holder.class, Transaction.class, Holder.class));}}. Note that this method
signature contains two Holder objects.
* When {{ServiceInterfaceStrategy}} goes through {{#analyzeServiceInterface}} it uses the
name of the class object passed in the signature as key in the {{ServiceInterfaceStrategy.inTypeNameToQName}}
Map. 
* Because there are two {{Holder}} instances in the signature it means that only one of the
two QName which are added to the map will be found, as they both rely on the same {{Holder.class}}-based
key
* The problem above occurs when {{ServiceInterfaceStrategy#findQNameForSoapActionOrObject}}
reads from {{ServiceInterfaceStrategy.inTypeNameToQName}}, getting the exact same QName out
of the map for both objects, hence generating erroneous xml (Note that nothing fails, it just
sends rubbish to the webservice)

*A solution*
Files that I "Patched" to get this case to work:
* org.apache.camel.dataformat.soap.name.ElementNameStrategy
* org.apache.camel.dataformat.soap.name.ServiceInterfaceStrategy
* org.apache.camel.dataformat.soap.name.TypeNameStrategy
* org.apache.camel.dataformat.soap.SoapJaxbDataFormat


My solution relies on the following:
* For the end user the "receipe" is still exactly the same with use of BeanInvocation
* I have created a utility class to generate suitable keys for adding/retrieving Holder objects
(see further down).
* I modified the method {{PatchedElementNameStrategy#findQNameForSoapActionOrObject(String
soapAction, Object object)}} to take an object parameter instead of a class. This gives this
method the correct tool (the object, not the class) to produce a key which actually retrieves
the correct QName

All this works fine for me and I would like to submit my patch to the project.
{{code}}
package org.apache.camel.dataformat.soap.name;

import javax.xml.ws.Holder;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public final class ElementNameStrategyUtils {

    private ElementNameStrategyUtils() {
        // utility class
    }

    /**
     * Generates a suitable key for adding a QName in one of the <code>Map<String,
QName></code> <code>PatchedServiceInterfaceStrategy</code>.
     *
     * @param type
     * @return
     */
    public static String getTypeNameForType(Type type) {
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            StringBuffer typeName = new StringBuffer();
            Class<?> rawTypeAsClass = (Class<?>) parameterizedType.getRawType();
            typeName.append(rawTypeAsClass.getName());
            for (int i = 0; i < parameterizedType.getActualTypeArguments().length; i++)
{
                Type actualTypeArg = parameterizedType.getActualTypeArguments()[i];
                typeName.append("-");
                typeName.append(getTypeNameForType(actualTypeArg));
            }
            return typeName.toString();
        } else {
            Class<?> typeAsClass = (Class<?>) type;
            return typeAsClass.getName();
        }
    }

    /**
     * Generates a suitable key for retrieving a QName from one of the <code>Map<String,
QName></code> <code>PatchedServiceInterfaceStrategy</code>.
     *
     * @param object
     * @return
     */
    public static String getTypeNameForObject(Object object) {
        if (object instanceof Holder) {
            Holder holder = (Holder) object;
            StringBuffer typeName = new StringBuffer();
            typeName.append(holder.getClass().getName());
            if (holder.value != null) {
                typeName.append("-");
                typeName.append(getTypeNameForObject(holder.value));
            }
            return typeName.toString();
        } else {
            return object.getClass().getName();
        }
    }


}
{{code}}

    
> Erroneous support of Jaxb web services taking serveral Holder arguments 
> ------------------------------------------------------------------------
>
>                 Key: CAMEL-5112
>                 URL: https://issues.apache.org/jira/browse/CAMEL-5112
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-soap
>    Affects Versions: 2.9.0
>         Environment: $> java -version
> java version "1.6.0_29"
> Java(TM) SE Runtime Environment (build 1.6.0_29-b11-402-11D50d)
> Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02-402, mixed mode)
> $> uname -a
> 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64
x86_64
>            Reporter: Florent Legendre
>
> Hi,
> *NB*
> I ran into a problem while using the camel-soap module. I have created a patched version
of the problematic classes and am totally open for submitting them for review in hope that
it could increase the chance for this bug to be fixed in a near future. 
> *The problem*
> I have to integrate with a web service with that type of signature (generated from the
original wsdl file with the help of wsimport):
> {code}
> @WebMethod
> @WebResult(name = "Details", targetNamespace = "http://example.com/service.xsd", partName
= "response")
> public Details fetchDetails(
>         @WebParam(name = "fetchDetails", targetNamespace = "http://example.com/service.xsd",
partName = "fetchDetails")
>         Personsearch fetchDetails,
>         @WebParam(name = "Session", targetNamespace = "http://example.com/service.xsd",
header = true, mode = WebParam.Mode.INOUT, partName = "Session")
>         Holder<Session> session,
>         @WebParam(name = "Transaction", targetNamespace = "http://example.com/service.xsd",
header = true, partName = "Transaction")
>         Transaction transaction,
>         @WebParam(name = "Transactioninfo", targetNamespace = "http://example.com/service.xsd",
header = true, mode = WebParam.Mode.OUT, partName = "Transactioninfo")
>         Holder<Transactioninfo> transactionInfo)
>         throws FetchDetailsException
>     ;
> }}
> {code}
> The call to the web service is set up as documented in the wiki (all this done in the
context of a {{Processor#process(Exchange)}} method)
> * Create a bean invocation
> * Set the Method object representing the method to be called (fetchDetails in my case)
on the bean invocation
> * build the parameters for the method call and set them on the bean invocation.
> * Set the bean invocation in the out body of the exchange
> This kind of setup leads to incorrect generation of the xml sent to the webservice. The
reason for this is:
> * When specifying the method to invoke i have to write {{beanInvocation.setMethod(ServicePortType.class.getMethod(WS_METHOD_NAME,
Personsearch.class, Holder.class, Transaction.class, Holder.class));}}. Note that this method
signature contains two Holder objects.
> * When {{ServiceInterfaceStrategy}} goes through {{#analyzeServiceInterface}} it uses
the name of the class object passed in the signature as key in the {{ServiceInterfaceStrategy.inTypeNameToQName}}
Map. 
> * Because there are two {{Holder}} instances in the signature it means that only one
of the two QName which are added to the map will be found, as they both rely on the same {{Holder.class}}-based
key
> * The problem above occurs when {{ServiceInterfaceStrategy#findQNameForSoapActionOrObject}}
reads from {{ServiceInterfaceStrategy.inTypeNameToQName}}, getting the exact same QName out
of the map for both objects, hence generating erroneous xml (Note that nothing fails, it just
sends rubbish to the webservice)
> *A solution*
> Files that I "Patched" to get this case to work:
> * org.apache.camel.dataformat.soap.name.ElementNameStrategy
> * org.apache.camel.dataformat.soap.name.ServiceInterfaceStrategy
> * org.apache.camel.dataformat.soap.name.TypeNameStrategy
> * org.apache.camel.dataformat.soap.SoapJaxbDataFormat
> My solution relies on the following:
> * For the end user the "receipe" is still exactly the same with use of BeanInvocation
> * I have created a utility class to generate suitable keys for adding/retrieving Holder
objects (see further down).
> * I modified the method {{PatchedElementNameStrategy#findQNameForSoapActionOrObject(String
soapAction, Object object)}} to take an object parameter instead of a class. This gives this
method the correct tool (the object, not the class) to produce a key which actually retrieves
the correct QName
> All this works fine for me and I would like to submit my patch to the project.
> {code}
> package org.apache.camel.dataformat.soap.name;
> import javax.xml.ws.Holder;
> import java.lang.reflect.ParameterizedType;
> import java.lang.reflect.Type;
> public final class ElementNameStrategyUtils {
>     private ElementNameStrategyUtils() {
>         // utility class
>     }
>     /**
>      * Generates a suitable key for adding a QName in one of the <code>Map<String,
QName></code> <code>PatchedServiceInterfaceStrategy</code>.
>      *
>      * @param type
>      * @return
>      */
>     public static String getTypeNameForType(Type type) {
>         if (type instanceof ParameterizedType) {
>             ParameterizedType parameterizedType = (ParameterizedType) type;
>             StringBuffer typeName = new StringBuffer();
>             Class<?> rawTypeAsClass = (Class<?>) parameterizedType.getRawType();
>             typeName.append(rawTypeAsClass.getName());
>             for (int i = 0; i < parameterizedType.getActualTypeArguments().length;
i++) {
>                 Type actualTypeArg = parameterizedType.getActualTypeArguments()[i];
>                 typeName.append("-");
>                 typeName.append(getTypeNameForType(actualTypeArg));
>             }
>             return typeName.toString();
>         } else {
>             Class<?> typeAsClass = (Class<?>) type;
>             return typeAsClass.getName();
>         }
>     }
>     /**
>      * Generates a suitable key for retrieving a QName from one of the <code>Map<String,
QName></code> <code>PatchedServiceInterfaceStrategy</code>.
>      *
>      * @param object
>      * @return
>      */
>     public static String getTypeNameForObject(Object object) {
>         if (object instanceof Holder) {
>             Holder holder = (Holder) object;
>             StringBuffer typeName = new StringBuffer();
>             typeName.append(holder.getClass().getName());
>             if (holder.value != null) {
>                 typeName.append("-");
>                 typeName.append(getTypeNameForObject(holder.value));
>             }
>             return typeName.toString();
>         } else {
>             return object.getClass().getName();
>         }
>     }
> }
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Mime
View raw message