Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attachments in Response error #10

Open
kdickerson opened this issue Mar 1, 2012 · 17 comments
Open

Attachments in Response error #10

kdickerson opened this issue Mar 1, 2012 · 17 comments

Comments

@kdickerson
Copy link

Not sure if cxf-client can do anything about this or not, but I'm not finding any useful information elsewhere.

I have a service method that takes a Holder for the response and a Holder for an attachment. When processing the response (which comes through correctly) I get an IndexOutOfBoundsException in HolderInInterceptor:

java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at org.apache.cxf.message.MessageContentsList.get(MessageContentsList.java:79)
at org.apache.cxf.jaxws.interceptors.HolderInInterceptor.handleMessage(HolderInInterceptor.java:65)

I thought it might be this: https://issues.apache.org/jira/browse/CXF-1740
Which was spurred by this discussion: http://cxf.547215.n5.nabble.com/IndexOutOfBoundsException-in-MessageContentsList-td559159.html

However, the WSDL I'm using doesn't specify a namespace in the soap:body tags.

Regardless, Daniel Kulp suggests:

My suggestion is to change the spring configuration to add the wsdlLocation,
serviceName, and endpointName attributes to configure in the proper wsdl
information to convert it to a wsdl first scenario like the "working" case.

I would try the indicated workaround, but I'm not sure how (very limited SOAP experience here). I thought perhaps I could try hardcoding something in WebServiceClientFactoryImpl.groovy at line 151 before calling clientProxyFactory.create():

clientProxyFactory.setWsdlLocation('....')
clientProxyFactory.setServiceName(javax.xml.namespace.QName.valueOf('...'))
clientProxyFactory.setEndpointName(javax.xml.namespace.QName.valueOf('...'))

But either I'm not doing it right or it won't work that way because I just get errors.

I'd be happy to try various changes to get things working if you have any ideas. Unfortunately, I can't post any details of my code.

@ctoestreich
Copy link
Member

Is there any way for you to recreate the issue with contrived code that is shareable? I am a unsure on a solution atm.

On Mar 1, 2012, at 5:18 PM, Kyle Dickerson reply@reply.github.com wrote:

Not sure if cxf-client can do anything about this or not, but I'm not finding any useful information elsewhere.

I have a service method that takes a Holder for the response and a Holder for an attachment. When processing the response (which comes through correctly) I get an IndexOutOfBoundsException in HolderInInterceptor:

java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at org.apache.cxf.message.MessageContentsList.get(MessageContentsList.java:79)
at org.apache.cxf.jaxws.interceptors.HolderInInterceptor.handleMessage(HolderInInterceptor.java:65)

I thought it might be this: https://issues.apache.org/jira/browse/CXF-1740
Which was spurred by this discussion: http://cxf.547215.n5.nabble.com/IndexOutOfBoundsException-in-MessageContentsList-td559159.html

However, the WSDL I'm using doesn't specify a namespace in the soap:body tags.

Regardless, Daniel Kulp suggests:

My suggestion is to change the spring configuration to add the wsdlLocation,
serviceName, and endpointName attributes to configure in the proper wsdl
information to convert it to a wsdl first scenario like the "working" case.

I would try the indicated workaround, but I'm not sure how (very limited SOAP experience here). I thought perhaps I could try hardcoding something in WebServiceClientFactoryImpl.groovy at line 151 before calling clientProxyFactory.create():

clientProxyFactory.setWsdlLocation('....')
clientProxyFactory.setServiceName(javax.xml.namespace.QName.valueOf('...'))
clientProxyFactory.setEndpointName(javax.xml.namespace.QName.valueOf('...'))

But either I'm not doing it right or it won't work that way because I just get errors.

I'd be happy to try various changes to get things working if you have any ideas. Unfortunately, I can't post any details of my code.


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10

@kdickerson
Copy link
Author

I will try to create something I can share. Hopefully I can provide something next week.

@kdickerson
Copy link
Author

Okay, I have a demo put together. It provides 4 servers and a grails client configured to talk to all of them. 2 provide attachments in the response and throw the exception. 1 uses holders but not attachments and works. And the last doesn't use holders or attachments and works. I tried to keep them all as similar as possible.

Unfortunately, github's issue tracker doesn't seem to support uploading a file. What's the best way for me to get this zip file to you?

@ctoestreich
Copy link
Member

Acetrike at gmail

On Mar 9, 2012, at 6:28 PM, Kyle Dickerson reply@reply.github.com wrote:

Okay, I have a demo put together. It provides 4 servers and a grails client configured to talk to all of them. 2 provide attachments in the response and throw the exception. 1 uses holders but not attachments and works. And the last doesn't use holders or attachments and works. I tried to keep them all as similar as possible.

Unfortunately, github's issue tracker doesn't seem to support uploading a file. What's the best way for me to get this zip file to you?


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10#issuecomment-4427456

@kdickerson
Copy link
Author

I sent you the zip file a few days ago, I assume you got it.

I've been doing more digging using a custom loggingInInterceptor to inspect what things look like just before the HolderInInterceptor runs.

The problem seems to be that when the Interceptor is trying to populate the Holder for the attachment it looks for the attachment in "inObjects" which is a MessageContentsList object, but the attachment isn't in inObjects, the attachment is perfectly available via the message.getAttachments() method right where it should be based on what the AttachmentInInterceptor does. So maybe something's wrong with how the classes are getting built from wsdl2java?

I've posted to the cxf-users mailing list with this information hoping someone there has an idea.

@ctoestreich
Copy link
Member

I got the files. Will be looking tomorrow; works been busy :/

Let me known if you find anything soon. I will ping you tomorrow after i start digging.

On Mar 12, 2012, at 5:52 PM, Kyle Dickerson reply@reply.github.com wrote:

I sent you the zip file a few days ago, I assume you got it.

I've been doing more digging using a custom loggingInInterceptor to inspect what things look like just before the HolderInInterceptor runs.

The problem seems to be that when the Interceptor is trying to populate the Holder for the attachment it looks for the attachment in "inObjects" which is a MessageContentsList object, but the attachment isn't in inObjects, the attachment is perfectly available via the message.getAttachments() method right where it should be based on what the AttachmentInInterceptor does. So maybe something's wrong with how the classes are getting built from wsdl2java?

I've posted to the cxf-users mailing list with this information hoping someone there has an idea.


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10#issuecomment-4463676

@ctoestreich
Copy link
Member

put this in a bat file at the project root to help out starting processes:

start java -cp soapServer_HoldersNoAttachment\src\build\classes noattachment.holders.soapserver.TestService_TestServicePort_Server
start java -cp soapServer_Mime\src\build\classes mime.soapserver.TestService_TestServicePort_Server
start java -cp soapServer_noHolders\src\build\classes noholders.soapserver.TestService_TestServicePort_Server
start java -cp soapServer_noMime\src\build\classes nomime.soapserver.TestService_TestServicePort_Server


From: Kyle Dickerson reply@reply.github.com
To: Christian Oestreich acetrike@yahoo.com
Sent: Monday, March 12, 2012 5:52 PM
Subject: Re: [cxf-client] Attachments in Response error (#10)

I sent you the zip file a few days ago, I assume you got it.

I've been doing more digging using a custom loggingInInterceptor to inspect what things look like just before the HolderInInterceptor runs.

The problem seems to be that when the Interceptor is trying to populate the Holder for the attachment it looks for the attachment in "inObjects" which is a MessageContentsList object, but the attachment isn't in inObjects, the attachment is perfectly available via the message.getAttachments() method right where it should be based on what the AttachmentInInterceptor does. So maybe something's wrong with how the classes are getting built from wsdl2java?

I've posted to the cxf-users mailing list with this information hoping someone there has an idea.


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10#issuecomment-4463676

@ctoestreich
Copy link
Member

I am still looking but I played around with the cxf code by copying their interceptor and duplicating it as a custom one. Trying to find the root cause, but adding some code to the custom interceptor (which is really just a HolderInInterceptor) I am able to get it to move on:

if (holder != null&& part.getIndex() < inObjects.size()) {
holder.value = inObjects.get(part);
inObjects.put(part, holder);
}

Will let you know what I find.

Code is at: https://github.com/ctoestreich/soapClient

C


From: Kyle Dickerson reply@reply.github.com
To: Christian Oestreich acetrike@yahoo.com
Sent: Monday, March 12, 2012 5:52 PM
Subject: Re: [cxf-client] Attachments in Response error (#10)

I sent you the zip file a few days ago, I assume you got it.

I've been doing more digging using a custom loggingInInterceptor to inspect what things look like just before the HolderInInterceptor runs.

The problem seems to be that when the Interceptor is trying to populate the Holder for the attachment it looks for the attachment in "inObjects" which is a MessageContentsList object, but the attachment isn't in inObjects, the attachment is perfectly available via the message.getAttachments() method right where it should be based on what the AttachmentInInterceptor does. So maybe something's wrong with how the classes are getting built from wsdl2java?

I've posted to the cxf-users mailing list with this information hoping someone there has an idea.


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10#issuecomment-4463676

@ctoestreich
Copy link
Member

I found a few articles on this, but am not exactly sure where to start implementing their suggestions in the wsdl or the service contract.

http://camel.465427.n5.nabble.com/java-lang-IndexOutOfBoundsException-in-cxf-producer-td468541.html

The call to the service works fine in SOAP ui.


From: Kyle Dickerson reply@reply.github.com
To: Christian Oestreich acetrike@yahoo.com
Sent: Monday, March 12, 2012 5:52 PM
Subject: Re: [cxf-client] Attachments in Response error (#10)

I sent you the zip file a few days ago, I assume you got it.

I've been doing more digging using a custom loggingInInterceptor to inspect what things look like just before the HolderInInterceptor runs.

The problem seems to be that when the Interceptor is trying to populate the Holder for the attachment it looks for the attachment in "inObjects" which is a MessageContentsList object, but the attachment isn't in inObjects, the attachment is perfectly available via the message.getAttachments() method right where it should be based on what the AttachmentInInterceptor does. So maybe something's wrong with how the classes are getting built from wsdl2java?

I've posted to the cxf-users mailing list with this information hoping someone there has an idea.


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10#issuecomment-4463676

@ctoestreich
Copy link
Member

The best I can tell there is a bug in their code, I am not sure if there is a work around for this situation. I would assume there is. What I can see is in the block:

for (MessagePartInfo part : parts) {
if (part.getIndex() != 0 && part.getTypeClass() != null) {
@SuppressWarnings("unchecked")
Holder holder = (Holder)outHolders.get(part.getIndex() - 1);
//adding the check allows this to continue on
//but it still kaks in the actual HolderInInterceptor
if (holder != null
&& part.getIndex() < inObjects.size()) {
holder.value = inObjects.get(part);
inObjects.put(part, holder);
}
}
}

there are 2 objects in the parts variable, but their indexes are 2 and 3. The outHolders has 3 items and correctly uses the part.getIndex() - 1 as there is no get(3) only get(2).

On the other hand the call to holder.value = inObjects.get(part); is

public Object get(MessagePartInfo key) {
Object o = super.get(key.getIndex());
return o == REMOVED_MARKER ? null : o;
}

which incorrectly uses the getIndex and there is no [3] element in inObjects.

I am not sure where else that call is used, but I bet it is pretty common. It seems like we have to somehow stick another null object into the inObjects somehow or the check has to be added to the HolderInInterceptor for bounds:

if (holder != null && part.getIndex() < inObjects.size()) {
holder.value = inObjects.get(part);
inObjects.put(part, holder);
}

I don't know what side effects this would have on the flow either. I am going to keep digging a bit tomorrow, but I am not sure if I have uncovered anything you already didn't know?!

C


From: Kyle Dickerson reply@reply.github.com
To: Christian Oestreich acetrike@yahoo.com
Sent: Monday, March 12, 2012 5:52 PM
Subject: Re: [cxf-client] Attachments in Response error (#10)

I sent you the zip file a few days ago, I assume you got it.

I've been doing more digging using a custom loggingInInterceptor to inspect what things look like just before the HolderInInterceptor runs.

The problem seems to be that when the Interceptor is trying to populate the Holder for the attachment it looks for the attachment in "inObjects" which is a MessageContentsList object, but the attachment isn't in inObjects, the attachment is perfectly available via the message.getAttachments() method right where it should be based on what the AttachmentInInterceptor does. So maybe something's wrong with how the classes are getting built from wsdl2java?

I've posted to the cxf-users mailing list with this information hoping someone there has an idea.


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10#issuecomment-4463676

@kdickerson
Copy link
Author

You can see my post to the cxf-users mailing list is here: http://mail-archives.apache.org/mod_mbox/cxf-users/201203.mbox/browser
Yes, the index mismatch is the proximate cause of the indexOutOfBoundsException but the problem that remains is that the attachment holder needs to get populated with the attachment and nothing seems to do that.

My suggestion in the mailing list post is that I can use an interceptor to stick the attachment on the end of the MessageContentsList and then the code runs and it gets put into the Holder. However, the Holder is supposed to hold a byte[] but that's not the object type of the attachment at this point.

It would seem logical, based on the code, that something is supposed to take the attachment, convert it to the correct type, and stick it in the MessageContentsList so that when HolderInInterceptor runs it just does what we expect and moves the attachment into the Holder.

Unfortunately, no one has responded to my post on the cxf-users list yet. But it seems like our answer is going to need to come from them. I don't think the issue is with the cxf-client plugin. If I'm lucky the solution will be to modify the generated classes somehow that will result in the correct processing. For the real application I don't control the WSDL or the server side, so altering the WSDL won't be a useful solution.

@ctoestreich
Copy link
Member

You might want to add some of the details of the code semantics i identified in my long winded last email. I think pointing out the specific code causing the bounds failure might spark them. I am guessing they haven't responded due to them pawning it off as a grails/plugin issue.

On Mar 13, 2012, at 5:30 PM, Kyle Dickerson reply@reply.github.com wrote:

You can see my post to the cxf-users mailing list is here: http://mail-archives.apache.org/mod_mbox/cxf-users/201203.mbox/browser
Yes, the index mismatch is the proximate cause of the indexOutOfBoundsException but the problem that remains is that the attachment holder needs to get populated with the attachment and nothing seems to do that.

My suggestion in the mailing list post is that I can use an interceptor to stick the attachment on the end of the MessageContentsList and then the code runs and it gets put into the Holder. However, the Holder is supposed to hold a byte[] but that's not the object type of the attachment at this point.

It would seem logical, based on the code, that something is supposed to take the attachment, convert it to the correct type, and stick it in the MessageContentsList so that when HolderInInterceptor runs it just does what we expect and moves the attachment into the Holder.

Unfortunately, no one has responded to my post on the cxf-users list yet. But it seems like our answer is going to need to come from them. I don't think the issue is with the cxf-client plugin. If I'm lucky the solution will be to modify the generated classes somehow that will result in the correct processing. For the real application I don't control the WSDL or the server side, so altering the WSDL won't be a useful solution.


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10#issuecomment-4487909

@kdickerson
Copy link
Author

I changed the thread name on the CXF Users mailing list to reflect the underlying issue in SwAInInterceptor instead of the IndexOutOfBoundsException in HolderInInterceptor. The new thread is here: http://mail-archives.apache.org/mod_mbox/cxf-users/201203.mbox/browser

Daniel Kulp says that at least one part of the problem is that the service isn't given access the WSDL when it is created and so some information (like MIME stuff) is not known because it's not captured during wsdl2java class generation.

I'm working on addressing this by modifying the cxf-client plugin to pass the wsdl location when creating the client. But I'm getting errors I need to track down. I'm just modifying the functions required to get the wsdl location to WebServiceClientFactoryImpl.groovy assignCxfProxy(...) and into the call to JaxWsProxyFactoryBean so it looks like this:

JaxWsProxyFactoryBean clientProxyFactory = new JaxWsProxyFactoryBean(wsdlURL:wsdlURL,
    serviceClass: serviceInterface,
    address: serviceEndpointAddress,
    bus: BusFactory.defaultBus)

This much is working and I can see in the logging that it is using the wsdlURL when generating the client. However it is choking on actually creating the service: Caught Exception: Could not find definition for service {http://soapserver.mime/}TestServiceService. I'm not sure if that's a complaint that the WSDL doesn't have a service with that name (the service is named TestServiceServicePorts) or if the problem is that it can't find a java class with that name (same name difference).

I'm going to keep working on it though.

@ctoestreich
Copy link
Member

Thanks for sticking with this issue and following up with making changes. I can peak at your fork if it is up to date and see if I can help at all if you hit a road block.

C


From: Kyle Dickerson reply@reply.github.com
To: Christian Oestreich acetrike@yahoo.com
Sent: Friday, March 23, 2012 3:29 PM
Subject: Re: [cxf-client] Attachments in Response error (#10)

I changed the thread name on the CXF Users mailing list to reflect the underlying issue in SwAInInterceptor instead of the IndexOutOfBoundsException in HolderInInterceptor. The new thread is here: http://mail-archives.apache.org/mod_mbox/cxf-users/201203.mbox/browser

Daniel Kulp says that at least one part of the problem is that the service isn't given access the WSDL when it is created and so some information (like MIME stuff) is not known because it's not captured during wsdl2java class generation.

I'm working on addressing this by modifying the cxf-client plugin to pass the wsdl location when creating the client. But I'm getting errors I need to track down. I'm just modifying the functions required to get the wsdl location to WebServiceClientFactoryImpl.groovy assignCxfProxy(...) and into the call to JaxWsProxyFactoryBean so it looks like this:

JaxWsProxyFactoryBean clientProxyFactory = new JaxWsProxyFactoryBean(wsdlURL:wsdlURL,
serviceClass: serviceInterface,
address: serviceEndpointAddress,
bus: BusFactory.defaultBus)

This much is working and I can see in the logging that it is using the wsdlURL when generating the client. However it is choking on actually creating the service: Caught Exception: Could not find definition for service {http://soapserver.mime/}TestServiceService. I'm not sure if that's a complaint that the WSDL doesn't have a service with that name (the service is named TestServiceServicePorts) or if the problem is that it can't find a java class with that name (same name difference).

I'm going to keep working on it though.


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10#issuecomment-4667289

@kdickerson
Copy link
Author

I still don't know why it's choosing the name TestServiceService as the service name to look for (and I'm still not sure if it's looking for that in the WSDL or java classes), but I was able to workaround it and get a working MIME response by providing a hard-coded service QName. When creating the JaxWsProxyFactoryBean I included the following:

def serviceQname = new QName('http://soapserver.mime/', 'TestServiceServicePorts')
JaxWsProxyFactoryBean clientProxyFactory = new JaxWsProxyFactoryBean(wsdlURL:wsdlURL,
  serviceName:serviceQname,
  serviceClass:serviceInterface,
  address: serviceEndpointAddress,
  bus: BusFactory.defaultBus)

This, in conjunction with passing the WSDL URL, correctly created the service to handle MIME attachments.

Perhaps you have a good enough understanding of the workings to know the appropriate way of getting the correct service name used? As I said, I don't know why it decides to look for TestServiceService instead of TestServiceServicePorts so either figuring out how to get it to correctly pick the service name, or providing a way to configure the service name as a workaround would work best.

Also, I don't know if it had an effect on this, but I updated the dependencies to the latest stable (2.5.2 for cxf, and 1.6.4 for wss4j):

dependencies {
    // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
    compile('org.apache.cxf:cxf-rt-frontend-jaxws:2.5.2') {
        excludes 'spring-web'
    }
    compile('org.apache.cxf:cxf-rt-frontend-jaxrs:2.5.2') {
        excludes 'xmlbeans', 'spring-web', 'spring-core'
    }
    compile('org.apache.ws.security:wss4j:1.6.4')
    compile('org.apache.cxf:cxf-rt-ws-security:2.5.2') {
        excludes 'spring-web'
    }
    // runtime 'mysql:mysql-connector-java:5.1.13'
}

Was there a particular reason you were running against older versions?

I'll try to get a fork up soon so you can compare what changes I've made. I'll just put in place the ability to configure the serviceName as a workaround for now and if you have a proper solution I'll look forward to seeing it.

@ctoestreich
Copy link
Member

In regards to the cxf version, I picked the same deps as the CXF plugin was using as to not cause conflicts with cxf versioning if someone was using the cxf plugin as well.

Not sure on the naming. We did experience an issue outside the scope of the plugin when using cxf libs in our java project in which the name of the objects created were not binding to the annotation-provided naming schema for the request and response object. It was not allowing us to remove the Response keyword from the response object. I don't think your issue is related, but I will dig into it a bit this week when I can find some free time.

Thanks again!


From: Kyle Dickerson reply@reply.github.com
To: Christian Oestreich acetrike@yahoo.com
Sent: Monday, March 26, 2012 12:54 PM
Subject: Re: [cxf-client] Attachments in Response error (#10)

I still don't know why it's choosing the name TestServiceService as the service name to look for (and I'm still not sure if it's looking for that in the WSDL or java classes), but I was able to workaround it and get a working MIME response by providing a hard-coded service QName. When creating the JaxWsProxyFactoryBean I included the following:

def serviceQname = new QName('http://soapserver.mime/', 'TestServiceServicePorts')
JaxWsProxyFactoryBean clientProxyFactory = new JaxWsProxyFactoryBean(wsdlURL:wsdlURL,
serviceName:serviceQname,
serviceClass:serviceInterface,
address: serviceEndpointAddress,
bus: BusFactory.defaultBus)

This, in conjunction with passing the WSDL URL, correctly created the service to handle MIME attachments.

Perhaps you have a good enough understanding of the workings to know the appropriate way of getting the correct service name used? As I said, I don't know why it decides to look for TestServiceService instead of TestServiceServicePorts so either figuring out how to get it to correctly pick the service name, or providing a way to configure the service name as a workaround would work best.

Also, I don't know if it had an effect on this, but I updated the dependencies to the latest stable (2.5.2 for cxf, and 1.6.4 for wss4j):

dependencies {
// specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
compile('org.apache.cxf:cxf-rt-frontend-jaxws:2.5.2') {
excludes 'spring-web'
}
compile('org.apache.cxf:cxf-rt-frontend-jaxrs:2.5.2') {
excludes 'xmlbeans', 'spring-web', 'spring-core'
}
compile('org.apache.ws.security:wss4j:1.6.4')
compile('org.apache.cxf:cxf-rt-ws-security:2.5.2') {
excludes 'spring-web'
}
// runtime 'mysql:mysql-connector-java:5.1.13'
}

Was there a particular reason you were running against older versions?

I'll try to get a fork up soon so you can compare what changes I've made. I'll just put in place the ability to configure the serviceName as a workaround for now and if you have a proper solution I'll look forward to seeing it.


Reply to this email directly or view it on GitHub:
https://github.com/ctoestreich/cxf-client/issues/10#issuecomment-4699972

@kdickerson
Copy link
Author

Just sent you a pull request from my updated fork.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants