Basic CDI (in WebSphere 8.5, for JAX-WS)
DougBreaux 270007SMYJ Comments (3) Visits (10388)
However, with object lifecycles now managed by JEE containers, like for JAX-WS or JAX-RS services, sometimes using Spring-managed beans is not as direct as I'd like. JEE 6's Cont
Most of my projects use Spring for other things as well, so I hadn't been willing to look down the CDI path just yet. However, I'm now working on some SOAP Web Service projects that don't yet use Spring, so I thought I'd give CDI a look.
What follows is the basics of configuring a "web" application that is both a JAX-WS service and a JAX-WS client to one or more other services. I need to inject both some interface implementation classes and some JEE Resource References into my service. In case documenting this particular example helps anyone else. Or just helps me clarify what I did and remember it in the future :-)
In my @WebService JAX-WS implementation class (or any other "service" / "servlet" class managed by the JEE container), I need to make use of a "business facade" interface implementation singleton. JEE 6 annotation @Inject enables this.
If I only have one such BusinessFacade implementation class defined in the application, this is sufficient to locate it. (Classes don't have to be annotated in order to have their instance(s) injectable as "Producers". They just have to meet some conventions: see Abou
If you have multiple implementation classes, you'll need to qualify the @Inject like with @Named.
By default, the "sco
Since I want this BusinessFacade instance to be a singleton, only initialized once for the whole application, I need to tell my implementation class that I want instances of it to have "Application" scope. I do that by annotating that class with @ApplicationScoped.
(@Singleton is from the EJB spec and is somewhat different from CDI's @App
Now, somewhere down my object chain, I have another object that calls another Web Service, via a JAX-WS client wrapper, and I need to inject the endpoint URL into that wrapper.
I manage that URL through a web.xml <resource-ref> that I can map to server Resource at deploy time:
To get that injected into my hand-written caller class, I use @Resource, specifying the same name used in <res-ref-name>:
Now, specific to JAX-WS client wrappers, I want to override the endpoint URL that was specified in the WSDL used to create the client code. The approach that seems cleanest to me is usin
The @PostConstruct annotation indicates a method (named whatever you want) to be called after a class instance is created. I'll use this to bind a (singleton) JAX-WS client wrapper (ServicePortType in the example) to the endpoint URL specified in the above injected @Resource:
private ServicePortType serviceEndpoint = null;
(Where Service and ServicePortType match whatever was generated from your WSDL.)
Note that I've annotated this particular class with @ApplicationScoped, so this @PostConstruct will only be called once. Another potential pattern would be to have this class not be a singleton but have the @PostConstruct method lazy-initialize and reuse a static ServicePortType instance.
Finally, logistically, your application must contain a beans.xml file in its WEB-INF directory in order for WebSphere to know to scan it for CDI annotations. This file can be completely empty.