Skip to main content

How to pass initial parameter to a handler in jaxws2?

22 replies [Last post]
jxf6483
Offline
Joined: 2005-07-14
Points: 0

I am trying to use handler chain for soapmessage processing.
The first step is to test the client side handler. I use the following custom-client.xml file to generate client side code

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

com.jtv.security.handler.testHandler
SecurityProvider

action
UsernameToken
user
Chris
passwordType
PasswordText
passwordCallbackClass
com.jtv.core.ws.endpoint.example.handlerresult.ClientPWCallback

but I got the following error:
Exception in thread "main" java.lang.IllegalArgumentException: Illegal to call getName() when event type is CHARACTERS. Valid states are START_ELEMENT, END_ELEMENT
at com.sun.xml.stream.XMLReaderImpl.getName(XMLReaderImpl.java:854)
at com.sun.xml.ws.util.HandlerAnnotationProcessor.parseHandlerFile(HandlerAnnotationProcessor.java:132)
at com.sun.xml.ws.util.HandlerAnnotationProcessor.buildHandlerInfo(HandlerAnnotationProcessor.java:87)
at com.sun.xml.ws.client.ServiceContextBuilder.processAnnotations(ServiceContextBuilder.java:173)
at com.sun.xml.ws.client.ServiceContextBuilder.build(ServiceContextBuilder.java:82)
at com.sun.xml.ws.client.WSServiceDelegate.(WSServiceDelegate.java:113)
at com.sun.xml.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:50)
at javax.xml.ws.Service.(Service.java:58)
at com.jtv.core.ws.endpoint.example.handlerresult.HandlerResult_Service.(HandlerResult_Service.java:42)
at com.jtv.core.ws.endpoint.example.handlerresult.HandlerResultClient.main(HandlerResultClient.java:8)

How could I get over this?

Thanks in advance,

Jian

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
bbissett
Offline
Joined: 2003-06-16
Points: 0

> However, I look at the sample code fromjavahandler,
> the following code is just put there
>
> @HandlerChain ( file="handlers.xml", name="Chain1")

Oh yeah -- there should also be a handlers.xml file at the same level as the class file. :)

If not, let me know!

jxf6483
Offline
Joined: 2005-07-14
Points: 0

Hi Bobby,

Thank you very much for keeping me updated of the change in the handler framework. It is good to know that AOP is used in the handler framework now.

Thanks again,

Jian

jxf6483
Offline
Joined: 2005-07-14
Points: 0

Hi Bobby,

Thank you for your quick response. Yes, the file handlers.xml is at the same level as the class file.

After I traced the code and found where the problem is. As in the sample fromjavahandler, I use the following handlers.xml






com.jtv.core.ws.security.handler.WSS4JHandler

deployment
server

....
SecurityProvider



But in the method parseHandlerFile(XMLStreamReader reader,
ClassLoader classLoader, QName serviceName, QName portName, String bindingId) at line 137:

while (reader.getName().equals(QNAME_HANDLER_CHAIN)) {
...

}

That means the reader first looks for "handler-chain" instead of "handler-chains". Thus, the handler-chains pair
in handlers.xml file must be removed, otherwise, the code will not parse the handler configuration. Perhaps you should double check that. It that is true, it would be better to update the handlers.xml in the samples in jaxws source.

After I removed the handler-chains pair in file handlers.xml, the method parseHandlerFile(...) can parse the configuration. But the init-param is ignored as we discussed in previous posts. Thus, I need to wait for the new spec.

Thanks again,

Jian

bbissett
Offline
Joined: 2003-06-16
Points: 0

>
>
> > xmlns:jws="http://java.sun.com/xml/ns/javaee">
[...]

Yep, the sample hasn't been updated to the new schema. I'll do that soon -- thanks for the reminder!

Seems you've figured out the schema pretty much from the parser code. As a simple example:



...

The port name or protocol patterns are described in jsr 109. Not sure if the final version is public yet or not, but it should be soon and we will include examples in the next release.

Cheers,
Bobby

jxf6483
Offline
Joined: 2005-07-14
Points: 0

Hi Bobby,

Thank you very much. I will wait for your detailed explains.

Could I ask a question about the initization procedure on the server side. Currently, I am working on the test suite for server handlers. We will use XML files as inputs to WSServlet to test the outputs. I notice that server side handlers are initialized by class WSServletContextListener. This class will call RuntimeEndpointInfoParser.parseEndpoints(XMLStreamReader) and then this method will call HandlerAnnotationProcessor.ParseHandlerFile(...) to get the init params. When I traced the code, I found the server always read WEB-INF/sun-jaxws.xml for handler chain information. If the server could not find any definition for the handler chain in sun-jaxws.xml, it seems that the handler chain will be null and no init param will be read .

However, I look at the sample code fromjavahandler, the following code is just put there

@HandlerChain ( file="handlers.xml", name="Chain1")

and no handler chain definition in sun-jaxws.xml. Thus, it seems that the handler chain will never be generated nor initialized, right? Or the handlers.xml will be read somewhere later? If that is the case, which method will read handlers.xml? My current server implementation is based on the same method in fromjavahandler and it seems that the server handler is never called. Perhaps I did not find the correct way to define server handlers. Could you please clarify this to me?

Thanks a lot,

Jian

bbissett
Offline
Joined: 2003-06-16
Points: 0

>
> However, I look at the sample code fromjavahandler,
> the following code is just put there
>
> @HandlerChain ( file="handlers.xml", name="Chain1")

The general idea is that you can specify handlers with this annotation when starting from java or with a customization file when starting from wsdl (which is turned into a handler chain annotation on the generated server classes). In either case, handlers that are specified in the deployment descriptor (sun-jaxws.xml) override any others.

So as you've seen, the sun-jaxws file is parsed and handlers are instantiated and initialized if they are in the file. Check out the init() method of com.sun.xml.ws.server.RuntimeEndpointInfo. This method is called at runtime, though I don't remember if it's when the servlet is started or when the first request comes in.

Anyway, line 328 checks to see if the binding already has a handler chain or not. If handlers were specified in sun-jaxws.xml, then there will already be handlers and the @HandlerChain annotation is ignored. Otherwise, it calls HandlerAnnotationProcessor.buildHandlerInfo() to parse the handler chain file if the annotation is present on the class.

Does that answer the question? Will still post when the
spec changes are finalized.

Cheers,
Bobby

jxf6483
Offline
Joined: 2005-07-14
Points: 0

I looked at the code. During the client initializion procedure, the client will call HandlerAnnotationProcessor:parseHandlerFile(XMLStreamReader, ClassLoader,QName,QName,String). In this function, there are a few lines as follows,

// init params (ignored)
while (reader.getName().equals(QNAME_HANDLER_PARAM)) {
skipInitParamElement(reader);
}

// headers (ignored)
while (reader.getName().equals(QNAME_HANDLER_HEADER)) {
skipTextElement(reader);
}

// roles (not stored per handler)
while (reader.getName().equals(QNAME_HANDLER_ROLE)) {
roles.add(XMLStreamReaderUtil.getElementText(reader));
XMLStreamReaderUtil.nextContent(reader);
}

It seems that the init param is ignored. I just wonder if this is the place that causes the problem.

Thanks,

Jian

bbissett
Offline
Joined: 2003-06-16
Points: 0

>
> It seems that the init param is ignored. I just
> wonder if this is the place that causes the problem.

That's part of it. It's a case where the RI is ahead of the publically available spec, so I'm waiting to find out if I can give details or not now about what's going on.

If you look a little further down that same method you'll get a hint though, heh heh. Until things are resolved, you should maybe use last week's weekly bundle rather than what's in the repository right now. I'll post later with more details.

Thanks,
Bobby

bbissett
Offline
Joined: 2003-06-16
Points: 0

> That's part of it. It's a case where the RI is ahead
> of the publically available spec, so I'm waiting to
> find out if I can give details or not now about
> what's going on.

Hi Jian,

Just to let you know what's going on, the jax-ws spec has changed the way the handler lifecycle works now. The spec can be found here if you're curious: http://jcp.org (jax-ws 2.0 is jsr number 224).

The main point is that init params in the descriptor file are no longer used with handlers. The init(Map) and destroy() methods are no longet part of javax.xml.ws.Handler. Instead, you can annotate a method with @PostConstruct or @PreDestroy (in the javax.annotation.* package) and these methods will be called after the handler in instantiated and when the server runtime is destroyed, respectively.

(Like before with init(Map), any handler you create yourself and add programatically won't have lifecycle methods called by the jax-ws runtime. In this case, you're the "container" if that makes sense.)

The big change for handler code is that the annotated methods must return void and can take no parameters. So if you have a method in your handler such as:

@PostConstruct
public void initializeMePlease() {...}

...it will no longer have a Map passed to it. So you may need to make some changes to your handlers to hard code values or look them up somewhere else. In the app server environment you can use env-entry information to be passed in, but I don't have any more information about that.

I hope that gets you caught up. I'm sorry that your init-param questions and the spec changes happened with such timing that I had to keep changing my answers to you so fast!

Cheers,
Bobby

jxf6483
Offline
Joined: 2005-07-14
Points: 0

Hi Bobby,

I start to work on the handlerchain again to follow the new specification. Since I cannot pass the init-params to the handler from the handlerchain annotation, it seems not convenient to use the handler chain now. As you know, usually many handler instances with different configurations of a handler will be used in one application. Hard code is not possible here. If I use an input file, I don't know if the file will be on the same level as the endpoint class. If not, that also means all instances will use the same input file, right? The problem is still there.

I read JSR 250 and saw the follow description,

"The runtime MUST then carry out any injections requested by the handler, typically via the javax.annotation.Resource annotation. After all the injections have been carried out, including in the case where no injections were requested, the runtime MUST invoke the method carrying a javax.annotation .PostConstruct annotation, if present."

It seems the @Resource annotation can be used as injecting init-params. I looked at the class HandlerAnnotationProcessor, there is indeed processing for
@PostConstruct, but seems nothing for @Resource processing. Thus, I can not see how the injection is done. The handler samples provided with the code are too simple and I cannot find any good example for the new handlerchain. Do you have any good samples for that?

Thanks in advance,

Jian

bbissett
Offline
Joined: 2003-06-16
Points: 0

> I read JSR 250 and saw the follow description,
>
> "The runtime MUST then carry out any injections
> requested by the handler, typically via the
> javax.annotation.Resource annotation. After all the
> injections have been carried out, including in the
> case where no injections were requested, the runtime
> MUST invoke the method carrying a javax.annotation
> .PostConstruct annotation, if present."

My current understanding is that this applies in the EE case, and not in standalone jax-ws applications. I've asked about it and am hoping to get some answers to you soon. Currently I don't know any way to get init params into handlers anymore, and have started to do it by making my main handler class abstract and extend it with other handlers that only define the values I was passing into the handler at initialization time.

Another way is to include a properties file in your war file and have the handler read it in, but that's certainly not as easy as the old way.

Bobby

bbissett
Offline
Joined: 2003-06-16
Points: 0

Hi Jian,

I've received some more information, and I'm planning to implement the @Resouce injection for handlers in the jax-ws-sources workspace. Hopefully before Monday, so it will be available to you in the nightly builds.

Here's your chance for some input! My current suggestion is to map init params in handler descriptor (deployment descriptor, wsdl customization file, handler chain file) to Strings in the handler class that have the @Resource annotation. I'm leaning towards doing only Strings since the old Map passed to init() contained Strings. So, for instance, you could have init params such as:

name Bobby

number 42

And your handler would have:

@Resource
String name;
@Resource
String number;

If you wanted to convert 'number' to an int or other primitive type, that could be done in the @PostConstruct method.

Let me know if you have other suggestions. I'm hoping to get this added in the next day or two.

Thanks,
Bobby

bbissett
Offline
Joined: 2003-06-16
Points: 0

>
> Here's your chance for some input! My current
> suggestion is to map init params in handler
> descriptor (deployment descriptor, wsdl customization
> file, handler chain file) to Strings in the handler
> class that have the @Resource annotation.

Oops, turns out that is precluded by the jsr 109 specification, which states that init-params are used for jax-rpc handlers but not for jax-ws handlers. So I'm not sure what will happen yet.

But I'll post again when anything is resolved.

Cheers,
Bobby

jxf6483
Offline
Joined: 2005-07-14
Points: 0

Bobby,

Thanks a lot for your help. I do appreciate.

I thought of this problem before and know that it is impossible to pass init-params from the handler description file. Otherwise, the specification will not change the way the init-params are passed. Then, the only solution left seems to be to create a dependency manager that can find the approporiate objects to inject them into the fields annotated with the @Resource annotation.

I found an article from the web talking about how to inject @Resource using AspectJ as follows,

http://www.devx.com/Java/Article/29472/1954?pf=true

Since AspectJ is not used in Jaxws, it may not be useful for you.

I also found that in the glassfish project,

https://glassfish.dev.java.net/

they use EJB style @Resource injection. I think that one
may be closer. Since I have no right to modify the
code for Jax-ws source, I did not think about it further.

Hope this can be helpful.

Thanks again,

Jian

jxf6483
Offline
Joined: 2005-07-14
Points: 0

Hi Bobby,

I updated the latest Jaxws source from the CVS respository, the handler chain broke again. I debuged the code and found the init() function for the handler is not called at all. What is changed in the jaxws code that affects the handler chain? How should I modify my handler configuration file to make it work?

Thanks in advance,

Jian

jxf6483
Offline
Joined: 2005-07-14
Points: 0

Hi Bobby,

Yes, it works after I switch the soap role after the init-param statements.

Thank you so much for your help,

Jian

jxf6483
Offline
Joined: 2005-07-14
Points: 0

I dig into the code and found that the initial parameters are not passed to the handler, the size of the Map config is 0. Something is wrong with the jaxws handler source?

public void init (Map config) {
this.config = config;
}

Thanks,

Jian

bbissett
Offline
Joined: 2003-06-16
Points: 0

> I dig into the code and found that the initial
> parameters are not passed to the handler, the size of
> the Map config is 0. Something is wrong with the
> jaxws handler source?

This was fixed a while ago (was changed so that init was always called). However, the whole handler life cycle is about to change. See next post.

Bobby

jxf6483
Offline
Joined: 2005-07-14
Points: 0

Hi Bobby ,

Thank you very much for your response.

I changed the init-param parameters into pairs as you suggested. The wsimport tool generates a handler xml file for me as follows,





com.jtv.core.ws.security.handler.WSS4JHandler
SecurityProvider

deployment
client


flow
request-only


action
UsernameToken


user
Chris


passwordType
PasswordText


passwordCallbackClass
com.jtv.core.ws.endpoint.example.handlerresult.ClientPWCallback



I also checked out the latest jaxws jars from the CVS repository. Then I run the client program, but still got the following error:

Exception in thread "main" java.lang.IllegalArgumentException: Illegal to call getName() when event type is CHARACTERS. Valid states are START_ELEMENT, END_ELEMENT
at com.sun.xml.stream.XMLReaderImpl.getName(XMLReaderImpl.java:854)
at com.sun.xml.ws.util.HandlerAnnotationProcessor.parseHandlerFile(Unknown Source)
at com.sun.xml.ws.util.HandlerAnnotationProcessor.buildHandlerInfo(Unknown Source)
at com.sun.xml.ws.client.ServiceContextBuilder.processAnnotations(Unknown Source)
at com.sun.xml.ws.client.ServiceContextBuilder.build(Unknown Source)
at com.sun.xml.ws.client.WSServiceDelegate.(Unknown Source)
at com.sun.xml.ws.spi.ProviderImpl.createServiceDelegate(Unknown Source)
at javax.xml.ws.Service.(Service.java:58)
at com.jtv.core.ws.endpoint.example.handlerresult.HandlerResult_Service.(HandlerResult_Service.java:43)
at com.jtv.core.ws.endpoint.example.handlerresult.HandlerResultClient.main(HandlerResultClient.java:8)

The error occurred when the client tried to initialize the handler. Any hints for the solution?

Thanks alot,

Jian

bbissett
Offline
Joined: 2003-06-16
Points: 0

>
> The error occurred when the client tried to
> initialize the handler. Any hints for the solution?

I'm not sure what's causing the error. I'll try it with your file and maybe it will pop up. Will respond soon.

Cheers,
Bobby

bbissett
Offline
Joined: 2003-06-16
Points: 0

Hi Jian,

The problem is that the element comes before the init params, when the schema has it after. Sorry about the confusing error message, but what's happening is that the handler class is read, then it looks for init params and doesn't see any, then it finds the soap roles and parses those. After that, it expects the element and fails because there are more opening elements.

I've added some name checking to help figure out what's going on, since "wrong element found, expecting..." is more helpful than the message you were seeing.

So switch the roles element to after the params and see if that works for you.

Cheers,
Bobby

bbissett
Offline
Joined: 2003-06-16
Points: 0

Hi,

Try wrapping each initialization parameter in an init-param element, like this:

name1 value1

name2 value2

...rather than specifying mulitple names and values for one param like this:

name1 value1 name2 value2

See if that does it. If not, you may have a version of the class before the work was done to match the newest schema. If that's the case, you can update the jaxws jars or maybe I can figure out what that version is expecting.

Cheers,
Bobby