generally we use Spring context in servlet as follows
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servlet.getServletContext());
SomeBean someBean = (SomeBean) ctx.getBean("someBean");
But in REST service declared using annotation is not actually servlet. So we do not get getServletContext()
How handle this ?
answer
1) By passing context as parameter to method
#GET
#Path("/create")
#Produces(MediaType.TEXT_PLAIN)
public String createCustomer(#Context ServletContext servletContext){
2) Other solution is using ApplicationContextAware
which is explained here
To get the application context you can have your service implement ApplicationContextAware. Then when the service is created, Spring will call the setApplicationContext method to provide you with the application context. Inside that method you can then store the provided context for later use.
Related
Lets say I inject an ApplicationContext into a bean. I can then discover all the beans annotated with RestController. How would I discover the base URL associated with said beans?
Example:
#Component
public class ServiceEnumerator {
#Autowired
private ApplicationContext context;
#PostConstruct
private void postConstruct() {
final Map<String, Object> beansToExpose = context.getBeansWithAnnotation(RestController.class);
}
}
As per standard, Base URL (Context root) needs to setup in configuration file.
Not sure if below will help you....Try to inject HttpServletRequest in controller then from controller, pass it to required service
#Context
private HttpServletRequest httpRequest;
LOGGER.info("URL "+httpRequest.getRequestURI());
will give /services/v1/hello if your URL is http://localhost:8080/services/v1/hello
This could be possible by retrieving bean definition from bean factory and parsing its metadata. for instance:
retrieve beanFactory from your application Context
getting your bean definition from bean factory
retrieving its metadata
fetching attributes
metadata.getAnnotationAttributes(
"org.springframework.web.bind.annotation.RestController")
I am unable to configure HttpServletRequest in application context in my spring environment.
below is the code I tried:
<bean id="request" class="javax.servlet.http.HttpServletRequest">
</bean>
<bean id="rwEloquaControllerService" class="com.rightwave.eloqua.RWEloquaControllerService">
<property name="request" ref="request" />
</bean>
RWEloquaControllerService class code for getter setter:
HttpServletRequest request;
public HttpServletRequest getRequest() {
return request;
}
public void setRequest(HttpServletRequest request) {
this.request = request;
}
But when I start my server, exceptions occurred due to application context error. can any one tell me how to configure HttpServletRequest object in application context.
Let's talk about some basic concepts first.
In my Knowledge, it's not possible to instantiate an interface in application context. How do you new an interface without give it real implementation? It's impossible.
You write bean in application context so that Spring can instantiate them. However, the request you want is generated by servlet container. It's not created by Spring.
If you want to inject request in your controller, just add the following code in your controller. Spring doesn't create the request, Spring just get it from servlet container then inject it into the controller.
private #Autowired HttpServletRequest request;
Based on your comment:
Can I not instantiate an interface in application context. Basically, I need request object to get context, then springContext and then get a bean. So at first point I need request
Simply make you controller implement org.springframework.context.ApplicationContextAware. You will have to add the public void setApplicationContext(ApplicationContext applicationContext) throws BeansException method, which you can use to set the provided applicationContext to a member variable.
You can then use it to query the context for spring-managed beans.
Note: the setApplicationContext method will be invoked by Spring after your controller has been created but before afterPropertiesSet is invoked (if you implement InitializingBean).
I have my REST controller and method inside:
#GET
#Path("/tests/{id}")
#Produces("application/json")
public Response getAvailableTestsNames(#PathParam("id") String id){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
StudentService studentService = (StudentService)context.getBean("studentService");
Set<TestDTO> testDTOs = studentService.getAvailableTestsNames(id);
return Response.status(200).entity(testDTOs).build();
}
How cain i avoid creating ApplicationContext each time? I want to create it on start and use #Autowired annotation to inject my beans
I also asked about that here:
jboss spring applicationContext load on start in web.xml
However, the solution does not work for me. i still get an error
You can annotate your rest controller with #RestController annotation and start injecting your services with #Autowired.
In my SpringMVC project I need a certain tactic to call a class which does parse a xml file which does own my RMI server ip & port & the url must be relative to servletContext url :
HttpServletRequest request;
request.getServletContext().getRealPath("/WEB-INF/LABLAB/RMI-Config.xml")
I want to load these classes when I start my application in tomcat not when I call a Controller Class because my application depend to my RMI so before anything else I have to parse my file & using the IP & PORT fields to start connecting to my RMI & then call the rmi method to do some stuffs later on ...
now
how I'm gonna do it ? please tell me how I can initialize an instance of HttpServletRequest & give an intial value when I'm not on the Controller classes as well .
Thank you
You are using Spring, then you can create a class and implement IntializingBean. If you want to get hold of ServletContext you can simple use #Autowired annotation in your initializing bean. For e.g.:
#Component
public class SomeBean implements InitializingBean {
#Autowired
private ServletContext context;
public void afterPropertiesSet() throws Exception {
String path = context.getRealPath("/WEB-INF/LABLAB/RMI-Config.xml");
//do something.
}
}
As per docs:
IntializingBean - Interface to be implemented by beans that need to
react once all their properties have been set by a BeanFactory.
Or take a look here how to do this using ServletContextListener.
You need to implement the ServletContextListener interface and refer to it from your web.xml:
<listener>
<listener-class>InitializingListener</listener-class>
</listener>
The interface has a contextInitialized(ServletContextEvent sce) method, in which you can call sce.getServletContext(), so you don't need a HttpServletRequest.
If this doesn't work out, because you also need to access some of your Spring beans from the initializing class, then forget about implementing the ServletContextListener interface, and do the following instead:
Instantiate your initialization class via Spring (make a bean of that type).
Make the class implement ServletContextAware. This will cause Spring to inject the ServletContext into your class.
Define an init method on that bean (use the init-method bean attribute, or define a #PostConstruct annotated method)
Make all your Controller beans depend on the initializing bean by using the depends-on bean attribute. As a result, the initialaizing bean will be created before any Controller bean.
Without the last step, it cannot be guaranteed that your controllers won't start processing requests before the initialization bean finishes its work. However, specifying the depends-on attribute on each and every controller bean is also problematic, especially that they are usually created by applying the #Controller annotation instead of xml configuration. A nice workaround is described in this post.
I'm fresh new in Google Guice framework and i have a question regarding injecting in guice servlet and using RequestScope. Ok let me give some example from my code just to make the things clearly.
I have a bean class for example Bean ..
#RequestScope
public class Bean {
private String user;
private String pass;
// constructor which is #inject
// getters and setters
}
Here i've got a servlet
#Singleton
public class MainServlet extends HttpServlet {
doGet(HttpServletRequest request, HttpServletResponse response) {
.... some code
Injector injector = Guice.createInjector();
ValidUser validUser = injector.getInstance(ValidUser.class)
// Here i got the below exception
}
}
com.google.inject.ConfigurationException: Guice configuration errors:
1) No scope is bound to com.google.inject.servlet.RequestScoped.
at Bean.class while locating Bean
It's interesting here that servlet scope is singleton as we know.
And also how can i get from the http request - Bean instance?? because as far as i understand after a instance of a Bean class is injected it goes in the http request, right?
Any help or example is welcome.
Thanks
Br
You're creating and using an Injector inside the doGet method on your servlet... it has no chance to be aware of scope or of the current request or anything!
Guice Servlet requires that you set up all requests to go through the GuiceFilter and that you create a subclass of GuiceServletContextListener that creates the Injector that your whole application will use. This is all described in Guice user guide in the Servlets section.
Once you've done that, you can #Inject things in to your MainServlet (even using an #Inject annotated constructor). To get a request scoped instance of Bean inside the servlet, you'd need to inject a Provider<Bean> (since Bean has a smaller scope than the singleton servlet). Within a request, you can call beanProvider.get() to get the Bean for the current request.
Note that servlets are singletons because that's how they work in the normal Java servlet world as well... they're each only created once per application and that single instance is used for all requests to that servlet.