It came to my mind that we could simplify the client code by just
reusing the dispatch's operations that are already available in the
dispatch object.
Client client = ((DispatchImpl)dispatch).getClient();
InterfaceInfo iinfo =
client.getEndpoint().getEndpointInfo().getService().getInterface();
OperationInfo dpOpInfo =
iinfo.getOperation(oneWay ? INVOKE_ONEWAY_OPERATION_NAME :
INVOKE_OPERATION_NAME);
// add the desired operation name having the dispatch's invoke op
OperationInfo opInfo = iinfo.addOperation(operationName);
opInfo.setInput(dpOpInfo.getInputName(), dpOpInfo.getInput());
if (!oneWay) {
opInfo.setOutput(dpOpInfo.getOutputName(), dpOpInfo.getOutput());
}
for (BindingInfo bind :
client.getEndpoint().getEndpointInfo().getService().getBindings()) {
BindingOperationInfo bo = new BindingOperationInfo(bind, opInfo);
bind.addOperation(bo);
}
dispatch.getRequestContext().put(MessageContext.WSDL_OPERATION,
operationName);
2011/5/30 Aki Yoshida <[email protected]>:
> Hi Dan,
> Thanks for your explanation. I was looking at the dispatcher in a
> narrow scope. It makes sense to use a specific operation in general
> cases.
>
> It looks like Gunnar can programmatically add the right operation to
> the binding associated with the service at his client program. In this
> case, the dispatch mechanism can find the correct operation using the
> correct operation name and he can just use the generic disptach client
> without any WSDL by simply setting the appropriate operation for each
> scenario.
>
> This looks like:
> // dispatch = the dispatch instance created for Source.class
> // operationName = the operaiton qname
>
> Client client = ((DispatchImpl)dispatch).getClient();
> ServiceInfo info = client.getEndpoint().getEndpointInfo().getService();
>
> OperationInfo opInfo = info.getInterface().addOperation(operationName);
> MessageInfo mInfo = opInfo.createMessage(new
> QName(operationName.getNamespaceURI(), operationName.getLocalPart() +
> "Request"),
> Type.INPUT);
> opInfo.setInput(operationName.getLocalPart() + "Request", mInfo);
>
> MessagePartInfo mpi = mInfo.addMessagePart("parameters");
> mpi.setElement(true);
> mpi.setTypeClass(Source.class);
>
> // do the same for the output/response if not oneway
> ...
>
> // add the operation to the bindings
> for (BindingInfo bind :
> client.getEndpoint().getEndpointInfo().getService().getBindings()) {
> BindingOperationInfo bo = new BindingOperationInfo(bind, opInfo);
> bind.addOperation(bo);
> }
>
> // set the operation for this dispatch call
> dispatch.getRequestContext().put(MessageContext.WSDL_OPERATION,
> operationName);
>
> I think this is probably the right way for his use case.
> .
>
> Regards, aki
>
> 2011/5/27 Daniel Kulp <[email protected]>:
>> On Friday, May 27, 2011 1:58:17 PM Aki Yoshida wrote:
>>> Hi Dan,
>>> I don't think replacing the generic operation name with the user
>>> defined operation name so early in the phase helps because the
>>> operation name must match within ClientImpl to find one of the
>>> "dispatching operations".
>>
>> Actually, it doesn't. If the Dispatch is created via a Service object that
>> was created with the WSDL URL, it should be able to find a valid operation
>> for
>> it. This is also needed to be able to do things like WS-SecurityPolicy and
>> such with the Dispatch clients. To get the correct policies for the
>> operation, we need to know the operation, match it based on the WSDL, and get
>> the policies from there. The SecurityPolicyTest.testDispatchClient() test
>> case (in the ws-security systests) shows this, although this actually goes a
>> different route. If the operation is not specified on the RequestContext,
>> it
>> will use the qname on the root of the Source passed into the dispatch.invoke
>> to try and match the operation.
>>
>> Again, this ONLY works if the Service is constructed with a WSDL. If you
>> try
>> with a generic Service object, it won't.
>>
>> Dan
>>
>>
>>
>>> I also gave up on trying to use the annotations to make the matching
>>> work because there seems to be no way to construct a matching pair
>>> when you want to have the service name of your provider to be
>>> something different from the dispatch invoker’s generic service name.
>>>
>>> If we can set the namespace of the provider’s operation to the
>>> dispatch invoker's generic namespace while setting the namespace of
>>> the provider's service to the user defined one, that would work. In
>>> this case, the endpoint references will match with the user defined
>>> name and the binding operations will match with the invoker's generic
>>> operation name. But I couldn't find a way to do this.
>>>
>>> So I just went the other way and modifed a couple of lines in several
>>> Coloc classes to make it work. I don't know whether there is an easier
>>> approach.
>>>
>>> regards, aki
>>>
>>> 2011/5/27 Daniel Kulp <[email protected]>:
>>> > One thing you can try:
>>> >
>>> > If you do a
>>> > dispatch.getRequestContext().put(MessageContext.WSDL_OPERATION, new
>>> > QName("http://my.namespace", "myOperation"));
>>> >
>>> > before calling the invoke, it MAY be able to properly match the operation
>>> > name and thus not use the generic "invoke" operation. That said, you
>>> > MAY need to create the Dispatch client from a Service that was created
>>> > with a WSDL URL.
>>> >
>>> > Dan
>>> >
>>> > On Thursday, May 26, 2011 1:02:56 PM Gunnar Morling wrote:
>>> >> Hi,
>>> >>
>>> >> I'm trying to use CXF's coloc feature
>>> >> (http://cxf.apache.org/docs/coloc-feature.html). Things work fine when
>>> >> using a "real" client for accessing the service (meaning the generated
>>> >> service/port classes for my service).
>>> >>
>>> >> But I'm running into trouble when using a dynamic client, namely a
>>> >> JAX-WS dispatch client. The cause seems to be that in
>>> >> org.apache.cxf.binding.coloc.ColocOutInterceptor#isColocated() the
>>> >> name of the invoked operation is compared against the names hosted by
>>> >> the co-located server port. As the invoked method name is a generic
>>> >> one in the dispatch scenario ("invoke" actually) this comparison fails
>>> >> and instead of the coloc transport the standard transport using HTTP
>>> >> is performed.
>>> >>
>>> >> Is there anything I could do about this? If JAX-WS dispatch based
>>> >> clients are generally not supported, is there any other way to use the
>>> >> coloc transport in a generic manner? Or is this just an issue, for
>>> >> which I should open up a feature request in JIRA?
>>> >>
>>> >> Thanks in advance,
>>> >>
>>> >> Gunnar
>>> >
>>> > --
>>> > Daniel Kulp
>>> > [email protected]
>>> > http://dankulp.com/blog
>>> > Talend - http://www.talend.com
>>
>> --
>> Daniel Kulp
>> [email protected]
>> http://dankulp.com/blog
>> Talend - http://www.talend.com
>>
>