ServletConfig with out xml configuration in jsp? - java

How to set ServeltConfig param name and value in index.jsp page with out xml configuration like initParams in Servlet ? is Possible ?
<servlet>
<servlet-name>welcome</servlet-name>
<jsp-file>/index.jsp</jsp-file>
<init-param>
<param-name>website</param-name>
<param-value>www.google.com</param-value>
</init-param>
</servlet>

In JSP, we have implicit objects, in which we have config (This is the ServletConfig object associated with the page) object. But I guess we can't add parameters manually as their is not method for adding init parameter in ServletConfig interface.
If you want to save any parameters you can save in 4 scopes of JSP (page,request,session and application) and use it wherever you needed.
<c:set var="user" value="TestUser" scope="session"> //can set any value

You can do this with ServletContextListener. When the container starts up, it will call the ServletContextListener class. There you can set your params:
#WebListener
public class ContextListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
ServletContext ctx = servletContextEvent.getServletContext();
ctx.setAttribute("website", "www.google.com");
}
}

Related

Create bean in spring context

<bean id="configuration" class="com.mypackage.util.Configuration" factory-method="getInstance">
<property name="path" value="${path.props.app.dev}"></property>
</bean>
Then I have the following in my class
Configuration.getInstance();
Whereas the spring application context is loaded in another class Factory like this
private Factory() {
context = new ClassPathXmlApplicationContext("META-INF/spring.xml");
}
The problem is that before Factory class is accessed the context does not load and the configuration object gives null for path whereas when Factory is accessed and after that path property is accessed it gives the correct path.
Please tell me how to do it correctly? That is how can i get my member variable path with correct data without accessing Factory class.
Assuming that you are using Spring WebMVC. There are 2 ways:
Putting you bean configurations to dispatcher config XML (mvc-dispatcher-servlet.xml)
Remain your spring.xml and specify it in web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>spring.xml</param-value>
</context-param>
In both cases, you will no longer need a class like Factory. Besides, because of that Spring creates beans in singleton scope by default, you do not need to implement a getInstance() method for your com.mypackage.util.Configuration class.

Difference Between web-app's context-param and servlet's init-param?

I'm using Spring MVC. In a Controller class, I want to use the #Value annotation to inject a value that comes from a properties file:
#Value("${upload.dir}")
private String uploadDir;
So I need to put a property-placeholder somewhere.
The web.xml is typical:
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc-dispatcher-servlet.xml</param-value>
</init-param>
...
</servlet>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/business-context.xml</param-value>
</context-param>
First, I put the placeholder in business-context.xml. It doesn't work: "Could not autowire field".
Then I put it in mvc-dispatcher-servlet.xml, it works.
So I'm confused about these two contexts, are they the same one or different? Because the beans I defined in business-content.xml can be autowired, but the #Value doesn't work.
I don't want to put the placeholder in both xml files 'cause I have a long 'location' property. Also the business-context.xml will be used by some jobs, so it cannot be omitted.
Any way to make placeholder defined in business-context.xml become visible in mvc-dispatcher-servlet.xml as well?
A BeanFactoryPostProcessor which is what the property-placeholder is will only operate (and be visible) to the application context it is defined in. This is by design. So no you cannot make a property-placeholder from a parent visible to a child context (well with some nasty hacks you could).
As a work around you could do the following in your business-context.xml
<util:properties id="applicationProperties" location="path-to-your-very-long-location" />
<context:property-placeholder properties-ref="applicationProperties" />
and this in your mvc-dispatcher-servlet.xml.
<context:property-placeholder properties-ref="applicationProperties" />
Define the same <context:property-placeholder ../> in both xml context and simply reference the already loaded properties. Added advantage the properties are only loaded once.

Bean in DispatcherServlet accessing sibling bean

We have a web application with both a root application context (applicationContext.xml) and a dispatcher servlet (dispatcher-servlet.xml) defined in our web.xml like so:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
...
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
Due to the access restrictions, we obviously cannot access any of the DispatcherServlet beans from the root parent context.
But, what we'd like to be able to do is access the sibling beans. For example, in our dispatcher-servlet.xml we have:
<bean id="firstController" class="org.springframework.web.servlet.mvc.multiaction.MultiActionController">
...
</bean>
<bean id="secondController" class="org.springframework.web.servlet.mvc.multiaction.MultiActionController">
...
</bean>
How can we access the secondController from inside firstController, without requiring that it be passed in as a constructor-arg, or set as a property?
We're using WebApplicationContextUtils.getWebApplicationContext(...) to access siblings in the root applicationContext.xml, but we'd like to do the same thing in the child context. (From within one of the children.)
you can get an ApplicationContext object using
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dispatcher-servlet.xml")
This is assuming dispatcher-servlet.xml is in class path. context object has to be cached.
Then use context.getBean() to access beans from any where.
Other option seems to be , use overloaded method where we can pass the context attribute name. I have not used it.
WebApplicationContextUtils.getWebApplicationContext(ServletContext sc, String attrName)

Configurating Spring Ioc with Servlets

I'm new in Spring and want to connect spring ioc into my small(test) web-app.
I have such Servlet ProductServlet:
public class ProductServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
private RequestHelper requestHelper;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request);
}
private void processRequest(HttpServletRequest request){
requestHelper.process(request);
}
public RequestHelper getRequestHelper() {
return requestHelper;
}
public void setRequestHelper(RequestHelper requestHelper) {
this.requestHelper = requestHelper;
}
}
and my web.xml:
<servlet>
<servlet-name>ProductServlet</servlet-name>
<servlet-class>com.epam.productshop.controller.ProductShop</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ProductServlet</servlet-name>
<url-pattern>/ProductServlet</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-config.xml
</param-value>
</context-param>
and also I have such spring configuration xml:
<bean id="factory" class="com.epam.productshop.readerfactory.ReaderFactory">
<property name="file" value="/xml/products.xml" />
</bean>
<bean id="requestHelper" class="com.epam.productshop.requesthelper.RequestHelper" scope="singleton">
<property name="factory" ref="factory" />
</bean>
<bean name="ProductServlet" class="com.epam.productshop.controller.ProductServlet" scope="singleton">
<property name="requestHelper" ref="requestHelper"/>
</bean>
and I have such problem:
I want spring set requestHelper object into my servlet during servlet init(). but instead of this it's gives me nullpointer.
I'm trying to implement my servlet from HttpRequestHandler, writing SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, getServletContext()); into init() method and other things that i see in the internet but all this things doesn't solve my problem.
Please help me
In your question you have
<bean name="ProductServlet" class="com.epam.productshop.controller.ProductServlet" scope="singleton">
<property name="requestHelper" ref="requestHelper"/>
</bean>
You cannot instantiate servlets with Spring container, they are instantiated by servlet container. You're merely declaring another instance of ProductServlet.
So, when the Servlet init() method is called you should call
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, getServletContext());`
To inject the requestHelper declare an #Autowired annotated field or property in your servlet:
private RequestHelper requestHelper;
#Autowired
public void setRequestHelper(RequestHelper requestHelper){
this.requestHelper = requestHelper;
}
from processInjectionBasedOnServletContext javadoc:
Process #Autowired injection for the given target object, based on the
current root web application context as stored in the ServletContext.
Here is a solution, which might help you:
public class ProductServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
private RequestHelper requestHelper = null;
private requestHelperInit(HttpServletRequest request)
{
if(requestHelper == null)
{
ApplicationContext ap = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
requestHelper = ap.getBean(RequestHelper.class);
}
}
}
Then call requestHelperInit(request) method in either your doGet() or doPost() method as the first statement.
If you are still looking for a solution, then I hope this will help you out.
You have a couple of choices. If you really want to inject a servlet, the problem is that the servlet container is already in charge of creating the servlet. Since injections are a creation time occurence, and it's a bit hard to get at this servlet creation, you have to use less elegant solutions. However, this question explains how to inject servlets.
On the other hand, you might consider aborting this approach. If you are really creating a web application, it's fairly uncommon to code directly to the servlet api. Why not choose one of the many web application frameworks that sit on top of the servlet api and provide higher level functionality, aka bells and whistles. One of the bells and whistles is that these frameworks provide convenient integration with Spring so you can easily inject your code. For instance, Struts 2 has a spring plugin that allows you to use spring to inject all of the objects created by the framework, including framework infrastructural components.

RESTEasy will not map my Spring bean with custom Spring ContextLoader

RESTEasy 2.0.1GA
Java 1.6
Spring 3.0.3
I have tried everything I can, and cannot make head or tail of what's going on. I have a Spring MVC application, however I'd like to have some RESTEasy endpoints available outside the Spring MVC app, but in the same container, ultimately being able to wire in the same beans.
As a first step, I'm simply trying to stand-up RESTEasy inside the container, serving requests from a Spring-configured bean. I have tried the boilerplate from the instructions and have also tried manual setup, to no avail.
Bean
#Resource
#Path("/")
public class NeighborComparison {
private String foo;
#GET #Path(value="customer") #Produces("text/plain")
public String getNeighborComparison() {
return "foo";
}
}
web.xml
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/api</param-value>
</context-param>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<!-- NOT configuring SpringContextLoaderListener because I declare my own, so if I do, everything
blows up, plus all it actually does is sanity check configuration -->
<listener>
<listener-class>com.example.MyCustomContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
applicationContext.xml
<bean id="resteasy.providerFactory" class="org.jboss.resteasy.spi.ResteasyProviderFactory"
factory-method="getInstance">
</bean>
<bean id="resteasy.dispatcher" class="org.jboss.resteasy.core.SynchronousDispatcher">
<constructor-arg ref="resteasy.providerFactory"/>
</bean>
<bean id="resteasy.spring.bean.processor" class="org.jboss.resteasy.plugins.spring.SpringBeanProcessor">
<description>
Add Resources and #Providers to the appropriate places
in Resteasy's infrastructure
</description>
<constructor-arg ref="resteasy.dispatcher"/>
</bean>
<bean id="neighborComparison" class="opower.api.customer.neighbor_comparison.NeighborComparison">
</bean>
According to the documentation, all I have to do is “manually register the RESTeasy BeanFactoryPostProcessor by allocating an instance of org.jboss.resteasy.plugins.spring.SpringBeanProcessor”. I believe this spring configuration does that.
Jetty starts and the app context spins up with no issues. Application works normally, however when I
> curl -H"Accept: text/plain" localhost:8080/ei/api/customer
("ei" is the application context). The log shows (this and only this):
2011-03-29 16:44:24,153 DEBUG [qtp-575315405-0] [EI] [] [asy.core.SynchronousDispatcher] PathInfo: /customer
2011-03-29 16:44:24,156 DEBUG [qtp-575315405-0] [EI] [] [asy.core.SynchronousDispatcher] Failed executing GET /customer
org.jboss.resteasy.spi.NotFoundException: Could not find resource for relative : /customer of full path: http://localhost:8080/ei/api/customer
Even if I could convince RESTEasy to show me the mappings, it seems that it's just not discovering my bean.
If I map it explicitly via the resteasy.resources context param, it works, though obviously doesn't have access to auto-wired Spring beans.
Anything else I can try? I have debug log on the entire RESTEasy codebase and I don't get any messages. I've also confirmed that Spring is, in fact, creating my bean, so it's just that RESTEasy isn't finding it.
Your resource class needs to be annotated with #Path annotation for RESTeasy to pick up on it during bootstrap:
#Path("/customer")
#Resource
public class NeighborComparison {
#GET #Path("/{customerId}") #Produces("text/plain")
public String getNeighborComparison(#PathParam("customerId") long customerId) {
return "foo";
}
}
Note the #Path("/{customerId}} annotation without which your #PathParam parameter would not have been mapped correctly, resulting in a pretty detailed exception (and an accompanying 500 response on the client side). Assuming the service is picked up by RESTeasy of course.
In addition if you don't use RESTeasy's SpringContextLoader, you have to make sure your SpringBeanProcessor instance is registered with the ApplicationContext. RESTeasy delegates to it by registering an ApplicationListener in SpringContextLoader:
ApplicationListener listener = new ApplicationListener() {
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent) {
ContextRefreshedEvent cre = (ContextRefreshedEvent) event;
ConfigurableListableBeanFactory autowireCapableBeanFactory = (ConfigurableListableBeanFactory) cre
.getApplicationContext().getAutowireCapableBeanFactory();
new SpringBeanProcessor(dispatcher, registry, providerFactory)
.postProcessBeanFactory(autowireCapableBeanFactory);
}
}
};
configurableWebApplicationContext.addApplicationListener(listener);
If using a custom context loader and not the RESTEasy-provided one, this code has to appear somewhere in your context loader so that everything gets wired up. A bit convoluted, yeah. It is SpringBeanProcessor that goes through all Spring beans and registers with RESTeasy those that have a #Path annotation somewhere in their hierarchy (type and their corresponding interfaces).

Categories