I'm using CXF to generate a web service from wsdl.
The generated web service has the annotation #WebService
How do i get a reference to spring bean from the web service?
All my spring beans are annotated with #Service, and I can access them
in my web application. How do I access them also from my web service?
I've tried the following:
public class TestWSImpl implements TestWSSoap{
#Resource
public WebServiceContext wsContext;
#Override
public String getTest() {
ServletContext servletContext= (ServletContext) wsContext.getMessageContext().get(MessageContext.SERVLET_CONTEXT);
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
return "Test";
}
}
But the getWebApplicationContext method returns null
When I replace getWebApplicationContext with getRequiredWebApplicationContext
I get an error message: No WebApplicationContext found: no ContextLoaderListener registered?
Anyone has an idea?
Thanks
Alon
If you were using JUnit 4.4 or higher you could inject it using the Spring 2.5 JUnit annotations. Here's an example.
http://hamletdarcy.blogspot.com/2008/12/autowired-junit-tests-with-spring-25.html
Of course it goes without saying that this approach requires that the web service be running in a web context when the test is started. Have you done that?
You also might prefer testing WSDL based services using SOAP UI.
It was a long time ago.
I'm looking on my code and I see that I put the following method
that should init the spring:
#PostConstruct
public void init(){
JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
svrFactory.setServiceClass(MyWebService.class);
svrFactory.setAddress("http://address.com");
svrFactory.setServiceBean(wsHandler);
svrFactory.getInInterceptors().add(new LoggingInInterceptor());
svrFactory.getOutInterceptors().add(new LoggingOutInterceptor());
svrFactory.create();
}
Please tell me if it solve you problem....
Related
I've been searching for hours to find a solution for my problem but I can't get it to work. I want to inject my Weld-managed service into a ConstraintValidator that is used to validate a User-Object that is posted to my JAX-RS Rest-Service. Everything is deployed to a glassfish 4.1 server.
I have a Service like this
#ApplicationScoped
public class UserService {
}
and I want to inject it into a ConstraintValidator like this
public class UniqueUserNameValidator implements ConstraintValidator<UniqueUserName, ApiUser> {
#Inject
private UserService service;
#Override
public void initialize(UniqueUserName constraintAnnotation) {
}
#Override
public boolean isValid(ApiUser value, ConstraintValidatorContext context) {
return service.getByUserName(value.getUserName()) == null;
}
}
the REST resource looks like this
#Path("users")
#Produces(MediaType.APPLICATION_JSON)
public class UserResource {
#Inject
UserService userService;
#POST
public Response createUser(#Valid ApiUser apiUser) {
ApiRepresentation created = userService.create(apiUser);
return Response.created(createURL(created)).build();
}
}
When I Post a json user object i get the following exception:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=UserService,parent=UniqueUserNameValidator,qualifiers={},position=-1,optional=false,self=false,unqualified=null,173822971)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)
at org.jvnet.hk2.internal.Utilities.justInject(Utilities.java:947)
at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:902)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:977)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:968)
at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:173)
I'm aware that jersey uses hk2 as DI provider and the ConstraintValidator is created using the InjectingConstraintValidatorFactory which in return uses the ResourceContext. Since HK2 doe know nothing about my WELD container managed beans it can not inject the proper service when creating the ConstraintValidator.
To fix this I am searching for
a) A way to provide JAX-RS (preferable a pure JAX-RS way without a dependency to jersey) with a custom ConstraintValidatorFactory to create the validator.
or
b) A way to force jersey to use WELD as the DI provider or tell hk2 to pickup all container managed beans WITHOUT manually adding every single bean to hk2.
I have no Idea how to use the bridge proposed here .
I appreciate any help.
Cheers
I also faced this issue with Jersey 2.25.x, Weld 2.4.x and Tomcat 8.x and haven't found a proper solution with #Inject.
As a workaround, I programmatically looked up for the bean instance using:
SomeSortOfBean bean = CDI.current().select(SomeSortOfBean.class).get();
Do you have the possibility to change the underlying JAX-RS implementation for your project?
When I had the same problem, I just switched from Jersey to RestEasy (fully certified JAX-RS implementation). http://resteasy.jboss.org/
Changing the implementation was easy enough: Just include the dependy through your favorite build automation tool (I use gradle):
compile 'org.jboss.resteasy:resteasy-servlet-initializer:3.0.11.Final'
Additionally, to make CDI work, include the resteasy-cdi JAX-RS CDI bridge:
compile 'org.jboss.resteasy:resteasy-cdi:3.0.11.
Lastly if you want the same JSON format, include the resteasy-jackson-provider:
compile 'org.jboss.resteasy:resteasy-jackson-provider:3.0.11.Final'
In the end, switching to resteasy gave me a lot less headache than trying to implement a Jersey fix.
I have an ExceptionMapper defined as following
#Provider
public class MyExceptionMapper implements ExceptionMapper<Throwable> {
#Inject
private Manager myManager;
#Override
public Response toResponse(Throwable exception) {
// My implementation
}
}
Deploying this code on glassfish 4 results with exception:
org.glassfish.hk2.api.UnsatisfiedDependencyException:
There was no object available for injection at
Injectee(requiredType=Manager,parent=MyExceptionMapper,qualifiers {}),position=-1,optional=false,self=false,unqualified=null,955636053)
When I use #Context instead of #Inject I do not see the exception but myManager is null
I tried making MyManager as #ManagedBean, #Singleton or an EJB (Stateless, Singleton) and non works
In JEE6 (with glassfish 3) you have to add
#javax.annotation.ManagedBean
to the provider implementation. Possibly this works also for Glassfish 4
As far as I know, this issues comes from the following. CDI is not in place to manage the dependencies of restful services and providers by default. But when adding #ManagedBean you enable CDI to create the instance.
Here is an example where I introduced CDI to a restful service using jersey.
You can follow the updates regarding this issue here https://java.net/jira/browse/JERSEY-2393
You could use OmniFaces Beans to get a CDI managed bean instance in your ExceptionMapper:
Beans.getInstance(Bean.class)
I'm using this with #javax.ejb.Stateless beans containing #javax.persistence.PersistenceContext.
What is the correct way to implement a stateless EJB 3.1 for invoking a web service. My client works as a Servlet, but I want to move the invocation into a EEJ bean. I have to add username and password in the SOAP header envelop to access the WS, which is working fine.
The service the the servlet is using looks like this;
#WebServiceClient(name = "MessageService", targetNamespace = "http://...", wsdlLocation = "...wsdl")
public class MessageService
extends Service
Can I wrap MessageService in a Stateless EJB or should the bean itself use #WebServiceRef (as in the tutorial) without wrapping the MessageService ?
Tutorial
Local Service
If the client and the provider lives in same EAR or WAR on the application server, can be invoked like a ordinal EJB. e.g.
#WebService
#Stateless
public class CalculatorBean implements Calculator {
public int add(int a, int b) {
return a + b;
}
}
The CalculatorBean is threadsafe. All business logic that occurs within the add method
is part of a container-managed transaction and not participate in any global transaction.
Alternatively, the client code can look up in the JNDI namespace.
Remote Service
The runtime can inject a service object or a port object into a member variable annotated with javax.xml.ws.WebServiceRef.
#WebServiceRef(CalculatorService.class)
private Calculator port;
The CalculatorService class is annotated with the javax.xml.ws.WebServiceClient annotation (the client of the service), which has a wsdlLocation attribute.
If you want to wrap the WebService into the EJB, see this answer. For read a discussion about this, see EJB and Web Services: getting the best of both worlds.
I have an application scoped managed bean which contains a list read from the database. Whenever another application makes changes to the database, it should trigger the web service to update the list in the managed bean.
I've tried
FacesContext context = FacesContext.getCurrentInstance();
ApplicationBean application= (ApplicationBean) context.getApplication().evaluateExpressionGet(context, "#{applicationBean}", ApplicationBean.class);
The context variable was null, probably because the web service isn't called in the JSF context.
The REST resource class looks something like this:
#Path("/application")
public class ApplicationResource {
#PUT
#Path("{id}")
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.TEXT_PLAIN)
public void updateIdCache(#PathParam("id") String internalid) {
ApplicationBean application = ???;
application.update(id);
return;
}
}
The application server in use is tomcat 6. How is it done correctly?
Thanks & best regards
Don't think what you want is possible with JSF managed beans.
CDI beans have this functionality though.
JAX-WS with CDI:
http://weblogs.java.net/blog/jitu/archive/2010/02/19/jax-ws-cdi-java-ee-6-0
CDI implementation weld is commonly used:
Getting started with weld (covers tomcat 6)
http://docs.jboss.org/weld/reference/1.0.0/en-US/html/gettingstarted.html
btw I love to work with CDI and I only use tomcat 6/7
I'm trying to inject spring bean into class annotated with #WebService and #SOAPBinding annnotations.
#WebService(targetNamespace = JAXWSMessageHandler.MY_URL)
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class JAXWSMessageHandler {
private StorageManager bufferContainer;
public void setBufferContainer(StorageManager storageManager){
this.bufferContainer = storageManager;
}
and I get the following exception:
Service class soap.service.JAXWSMessageHandler method setBufferContainer part {http://myurl/myproject/v1}setBufferContainer cannot be mapped to schema. Check for use of a JAX-WS-specific type without the JAX-WS service factory bean.
It seems that the operation used by spring is expected to be defined in WSDL by CXF. I think I can hack it with singleton mediator class that would allow communication from WebService class to my business class,however, it doesn't sound good to me and I'd like to do that properly. Any hints how to do that?
JAX-WS is interpreting the method signatures on the annotated class as web service operations. My guess is that if you used constructor injection (instead of setter injection), the problem would go away.
I think I have a better solution:
Presumably you are using #WebMethod to annotate the methods you want to expose on your web service?
Well you can also add a #WebMethod annotation to your setter method, and set the attribute 'exclude' to be true. This means that this method will not be expected to be defined in your wsdl.
#WebService(targetNamespace = JAXWSMessageHandler.MY_URL)
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class JAXWSMessageHandler {
private StorageManager bufferContainer;
#WebMethod(exclude=true)
public void setBufferContainer(StorageManager storageManager){
this.bufferContainer = storageManager;
}