Access Business Object in a servlet inside JSF / Spring application? - spring

Usually, i'm accessing business objects (services) with #ManagedProperty in a main class annotated with #ManagedBean.
Here, i have a Servlet and i want to inject my business objects.
The use of managedProperty doesn't work with the annotation #WebServlet.
When i use WebApplicationContext, it's working.
Does the use of WebApplicationContext is the clean way to do that or is there a cleaner method to do it ?
#WebServlet(urlPatterns ="/Graphic")
public class GraphicServlet extends HttpServlet {
// Method 1 - This is not working ( the usual way in a ManagedBean)
#ManagedProperty(value="#{participantBo}")
private ParticipantBo participantBo; // getters and setters added
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Method 2 - This is working
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
ParticipantBo participantBo = (ParticipantBo) springContext.getBean("participantBo");
List<Participant> myParticipants = participantBo.findAllParticipant();
for (Participant participant : myParticipants) {
System.out.println(participant.getId_study());
}
}
}

Using WebApplicationContext is one of the ways to access the Spring web context from where you want. In fact, if you are able to reach Spring beans using #ManagedProperty, it means you have tied JSF and Spring frameworks in some way. #ManagedProperty should work only for JSF managed beans. However, being your servlet totally independent from the framework, accessing the Spring context this way is a choice.
See also:
https://stackoverflow.com/a/12244697/1199132
Spring Integration with other frameworks

Related

In a Spring Boot application is a Bean Factory/Application context ever explicitly used?

I am fairly new to Spring Boot and it is my sense from looking at sample applications that if a Bean Factory is ever used, it is used "under the covers" by Spring Boot. Or are there cases when using Spring Boot that you would in fact want to explicitly obtain a bean using the Bean Factory?
Every once in a while, I access Spring ApplicationContext from a bean that I initialize with new (basically a non-Spring managed bean) as follows:
#Component
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext context;
public static ApplicationContext getApplicationContext() {
return context;
}
#Override
public void setApplicationContext(ApplicationContext ac)
throws BeansException {
context = ac;
}
}
and in wherever I need it:
SomeBean someBean = ApplicationContextProvider.getApplicationContext().getBean("testBean", TestBean.class);
This is because:
I have to access a singleton (say, a #Service or a #Repository) from a bean I initialize (new) and I cannot make my bean Spring managed for that case. (so no #Autowired).
I don't want to introduce #Configurable to the project because it brings in AspectJ, which might be overkill to introduce for this simple case.

ClassBridge with DAO class injected

I have a Hibernate Search ClassBridge where I want to use #Inject to inject a Spring 4.1 managed DAO/Service class. I have annotated the ClassBridge with #Configurable. I noticed that Spring 4.2 adds some additional lifecycle methods that might do the trick, but I'm on Spring 4.1
The goal of this is to store a custom field into the index document based on a query result.
However, since the DAO, depends on the SessionFactory getting initialized, it doesn't get injected because it doesn't exist yet when the #Configurable bean gets processed.
Any suggestions on how to achieve this?
You might try to create a custom field bridge provider, which could get hold of the Spring application context through some static method. When provideFieldBridge() is called you may return a Spring-ified instance of that from the application context, assuming the timing is better and the DAO bean is available by then.
Not sure whether it'd fly, but it may be worth trying.
Hibernate Search 5.8.0 includes support for bean injection. You can see the issue https://hibernate.atlassian.net/browse/HSEARCH-1316.
However I couldn't make it work in my application and I had implemented a workaround.
I have created an application context provider to obtain the Spring application context.
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext context;
public static ApplicationContext getApplicationContext() {
return context;
}
#Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
ApplicationContextProvider.context = context;
}
}
I have added it to the configuration class.
#Configuration
public class RootConfig {
#Bean
public ApplicationContextProvider applicationContextProvider() {
return new ApplicationContextProvider();
}
}
Finally I have used it in a bridge to retrieve the spring beans.
public class AttachmentTikaBridge extends TikaBridge {
#Override
public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
// get service bean from the application context provider (to be replaced when HS bridges support beans injection)
ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
ExampleService exampleService = applicationContext.getBean(ExampleService .class);
// use exampleService ...
super.set(name, content, document, luceneOptions);
}
}
I think this workaround it's quite simple in comparision with other solutions and it doesn't have any big side effect except the bean injection happens in runtime.

Spring Injection in JSP

I have a jsp page which needs a java code.
This java code inside jsp needs a service class.
Now my service class is java gets created using spring DI and DAO & other things are injected in service class using Spring.
But when i want to use it in jsp, how should I ask spring to provide me the object of service inside jsp?
JSP -> Java Code -> Service -> DAO
I am using struts2 & spring DI as frameworks.
You can create a class that is Spring-managed and application context aware. This class will provide Spring bean via static methods from anywhere in your code.
#Service
public class SpringBeansProvider implements ApplicationContextAware {
static private ApplicationContext applicationContext;
public static <T> T getBean(String beanName, Class<T> type) {
return applicationContext.getBean(beanName, type);
}
#Override
public void setApplicationContext(ApplicationContext context) {
applicationContext = context;
}
}
From anywhere in your code, use SpringBeansProvider.getBean("myBean", MyBean.class). Yes, this breaks down a concept of beans injection and mixes up static and non-static methods usage, but such kind of task always cause those unfair things.
You don't inject into JSP pages; you inject into the action class and access using normal S2 mechanisms.

Injection of HttpServletRequest in GWTP ActionHandler using Spring

I have implemented my GWT application using Spring + GWTP.
I want to access HttpServletRequest object into my ActionHandler class.
The ServerModule is Spring Configuration class (using #Configuration Annotation).
Now problem is how can I inject the current HttpServletRequest, ServletContext, ServletConfig in my ActionHandler using Spring.
Following is the definition of ServerModule:
#Configuration
#Import(DefaultModule.class)
public class ServerModule extends HandlerModule
{
#Bean
public UserVerficationActionHandler getUserVerificationActionActionHandler()
{
return new UserVerficationActionHandler();
}
}
In above Example I just want to inject the HttpServletRequest using Spring.
Any guidance on this highly appreciated.
Thanks.
The RequestProvider is your solution. It's a class in gwt-dispatch-server jar.
DefaultModule provides the RequestProvider bean so that you can just inject it into places you need it.
Take a look at the sourcec code for com.gwtplatform.dispatch.server.spring.configuration.DefaultModule which creates the RequestProvider as a DefaultRequestProvider which then defers to RequestContextHolder to do the work.
See the link for what you need to add to your web.xml to get this to work.

Spring bean injection in a main method class

I have a web application with spring 3.0. I need to run a class with main method from a cron that uses beans defined in appcontext xml(using component scan annocations). I have my main class in same src directory.
How can I inject beans from web context into main method. I tried to do it using
ApplicationContext context = new ClassPathXmlApplicationContext("appservlet.xml");
I tried to use AutoWired and it returns a null bean. So I used Application ctx and this is creating a new context (as expected) when I run main method. But is it possible that I can use existing beans from container.
#Autowired
static DAO dao;
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("xman- servlet.xml");
TableClient client = context.getBean(TableClient.class);
client.start(context);
}
You can not inject a Spring bean into any object that was not created by spring. Another way to say that is: Spring can only inject into objects that it manages.
Since you are creating the context, you will need to call getBean for your DAO object.
Check out Spring Batch it may be useful to you.
You may use a spring context for your main application, and reuse the same beans as the webapp. You could even reuse some Spring XML configuration files, provided they don't define beans which only make sense in a webapp context (request-scope, web controllers, etc.).
But you'll get different instances, since you'll have two JVMs running. If you really want to reuse the same bean instances, then your main class should remotely call some method of a bean in your webapp, using a web service, or HttpInvoker.
Try with this Main:
public class Main {
public static void main(String[] args) {
Main p = new Main();
p.start(args);
}
#Autowired
private MyBean myBean;
private void start(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath*:/META-INF/spring/applicationContext*.xml");
System.out.println("The method of my Bean: " + myBean.getStr());
}
}
And this Bean:
#Service
public class MyBean {
public String getStr() {
return "mybean!";
}
}
In order to address this issue, I have created https://jira.springsource.org/browse/SPR-9044. If you like the proposed approach, please vote for it.
Spring boot provides an official solution for this. Download a skeleton from
https://start.spring.io/
and make sure packaging in the pom.xml is set to jar. As long as you don't include any web dependency the application will remain a console app.

Resources