How do I load servlet-context.xml automatically? - java

I'm new to Spring Framework and am currently trying to figure out how to load a file called servlet-context.xml automatically at application start. This file contains a bean definition which I'd like to use using #Autowired in my application code.
Note: I know that I can do something like the following to manually load beans, but this doesn't work when you're using #Autowired:
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
SomeObjectType x = (SomeObjectType)context.getBean("someObjectType");
I found this code sample from another tutorial which sort of tells how to load servlet-context.xml, but it was taken from a web application project which used MVC pattern. I don't have an web-app using MVC, so I don't think it applies to me:
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
The contents of my servlet-context.xml file are the following:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<beans:bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<beans:property name="jndiName" value="java:comp/env/jdbc/Database"/>
</beans:bean>
</beans:beans>
So what's the cleanest and simplest way to load servlet-context.xml file?

you can uselistener to load context...
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/appServlet/servlet-context.xml
</param-value>
</context-param>

Related

Cannot reach endpoints in Spring App. XML config

I'm trying to understand how Spring exactly works so I've made a simple one-controller app. Probably I forgot something in xml configuration.
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
<bean class="com.example.dogsrestapplication.controller.DogsController"/>
</beans>
DogsController:
#RestController
#RequestMapping("/dogs")
public class DogsController {
#GetMapping
public Collection<Dog> getAll() {
return DOGS.values();
}
}
I got 404 in http://localhost:8080/dogs.
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
What's wrong in my config?
IDEA: run/debug configuration -> Deployement -> Application Context.
Intellij Idea inserted there a full artifact name. I found my endpoints after I had inserted there just /.

Not able to access Spring controller

I am trying to create a Spring RESTful API very a basic application from scratch, but I am not able to access the controller. I could access JSP file but not controller. I have tried with to annotate with #RestController as well but it didn't work. I am running on Tomcat 8.
Error is:
The origin server did not find a current representation for the target
resource or is not willing to disclose that one exists. WEB.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven />
<context:component-scan
base-package="com.controller />
<mvc:default-servlet-handler />
</beans>
My Controller is
#Controller
public class TransactionControllerImpl{
#Autowired
private TransactionService transactionService;
#RequestMapping(method = RequestMethod.GET, value="/transaction")
#ResponseBody
public String getTransactionList() {
try {
System.out.println("from controller");
return "HEllow rahul";//transactionService.getTransactionList();
}
catch (Exception e) {
return null;
}
}
If you are creating application context separately, you should provide context param and value as location of your context.xml file.
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.xml</param-value>
</context-param>
For your error the controller is not accessible,it might be due to :-
<context:component-scan
base-package="com.controller />
check if you have written correct base-package name or try using
<context:component-scan base-package="..package name..">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
Hope it helps.
Remove listener from web.xml because you have only one context xml. If you want to load multiple context xml add listener and context param.

Spring MVC RequestMapping

I'm in the early stages of learning to use Spring MVC. I've created a controller and applied a RequestMapping annotation to it. When I run the project, the index page displays as expected at index.htm, but when I navigate to the URI that should be pointing to my controller, I get a 404 error, even though the controller seems to have been detected by Spring and started. Please help me understand what I am failing to grasp here:
Here is my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
Here is my applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd>
<context:spring-configured/>
<context:component-scan base-package="org.blah.blah"/>
Here is my dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.htm">indexController</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
And, finally, here is my controller.
#Controller
#RequestMapping(value = "/hello")
public class Ctrl {
#RequestMapping(method = RequestMethod.GET)
#ResponseBody
public String hello(){
return "hello!";
}
}
EDIT: This is what my browser displays:
I was half-wrong in the comments to gravityplanx' answer.
When you specify a <mvc:annotation-driven /> in your servlet configuration, Spring registers a RequestMappingHandlerMapping bean which is meant to collect and map all your #Controller handler methods, ie. those annotated with #RequestMapping.
It does this by looking at all the beans in the current context. Remember that when you load a context with DispatcherServlet, call it the servlet context, if a context was loaded by a ContextLoaderListener, call it the root context, the root context is made a parent of the servlet context. By default, the RequestMappingHandlerMapping bean does not look at the root context, which is a parent of the servlet context.
In your case, the #Controller beans are declared implicitly in the root context (your applicationContext.xml) because of the <context:component-scan/> which scans classes annotated with
#Component or any of its specializations (#Controller for instance) and creates beans for them. So these beans are registered in the root context, where the RequestMappingHandlerMapping can't find them.
If instead you declare the <context:component-scan /> in the servlet context, then the #Controller (and other) beans are created in the servlet context where they are available to the RequestMappingHandlerMapping which can then register them to handle requests.
Note that <context:component-scan /> on its own doesn't do anything for the MVC stack. It needs further configuration, like <mvc:annotation-driven />. You should aim to specify packages that contain servlet specific beans in the servlet context and application wide beans in the root context.
Here's some literature:
What is the difference between ApplicationContext and WebApplicationContext in Spring MVC?
Difference between applicationContext.xml and spring-servlet.xml in Spring Framework
Your dispatcher servlet doesn't seem to be referenced correctly.
Replace:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
With:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>[insert the path to your dispatcher-servlet here]</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
And then move:
<context:spring-configured/>
<context:component-scan base-package="org.blah.blah"/>
From applicationContext to dispatcher-servlet

DispatcherServlet not forwarding my request to the controller

I am using spring framework for writing a web service application. There are not html or jsp pages in the application. It is purely web service.
This is my Controller class
#RequestMapping("/*")
public class Opinion {
private FeedbackService fs;
public Opinion(FeedbackService fs){
this.fs=fs;
}
#RequestMapping(value="/givefeedback",method=RequestMethod.POST)
public void Login(HttpServletRequest request,HttpServletResponse response) throws IOException, ClassNotFoundException
{
ObjectInputStream in=new ObjectInputStream(request.getInputStream());
serialize.Feedback feedback=(serialize.Feedback)in.readObject();
fs.writeFeedback(feedback);
response.setStatus(200);
}
My mvc-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<bean id="poll_Web" class="sef.controller.Opinion">
<constructor-arg ref="feedbackService" />
</bean>
<context:component-scan base-package="sef.controller" />
</beans>
My web.xml
<servlet>
<servlet-name>opinionDispacher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value> classpath:repository-config.xml /WEB-INF/mvc-config.xml
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>opinionDispacher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value> classpath:repository-config.xml /WEB-INF/mvc-config.xml
</param-value>
</context-param>
I am using the URL localhost:8080/feedback/givefeedback. The app is deployed as feedback.war. But the request is not at all forwarded to the controller. I am not sure why is this is happening. I am also not sure till which point the request goes in the chain.
You're missing
<mvc:annotation-driven/>
from your servlet context configuration. This element will discover #Controller beans and their #RequestMapping methods and register them as handlers.
You'll need to add the appropriate XML namespace and schema location for that namespace.
Make Opinion a #Controller and remove
#RequestMapping("/*")
it doesn't really serve any purpose.
You have also defined the Opinion bean twice in mvc-config.xml. Remove bean definition for bean id poll_Web.

Spring MVC annotation config problem

I'm trying to improve my spring mvc configuration so as to not require a new config file for every servlet I add, but I'm running into problems. I've tried using this tutorial as a starting point, but I'm running into an issue that I can't figure out.
The problem is that when I do a GET to my servlet, I get back a 404 error. Here's my config and a representative java snippet from a Controller:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>SightLogix Coordination System</display-name>
<description>SightLogix Coordination System</description>
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/application-context.xml
/WEB-INF/application-security.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/slcs/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/application-context.xml
/WEB-INF/application-security.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
application-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"
default-init-method="init" default-destroy-method="destroy">
<mvc:annotation-driven />
<context:component-scan base-package="top.level" />
</beans>
application-security.xml:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http>
<intercept-url pattern="/**" access="ROLE_MANAGER" requires-channel="https" />
<http-basic />
</http>
<authentication-manager>
<authentication-provider user-service-ref="myUserDetailsService">
<password-encoder hash="sha"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="myUserDetailsService"
class="path.to.my.UserDetailsServiceImpl">
</beans:bean>
</beans:beans>
Snippet of a Controller class (one of many, but they all look essentially like this):
#Controller
#RequestMapping("/foo.xml")
public class FooController
{
#RequestMapping(method=RequestMethod.GET)
public void handleGET(HttpServletRequest request, HttpServletResponse response) throws IOException
{
...
Can anyone tell me what I'm doing incorrectly?
Thanks!
The only thing out of place here is that you've used the same context config files for both the root webapp context and your servlet context. This is almost guaranteed to be a bad idea, and will result in a lot of weird behaviour. This may well be the cause of your problem.
The ContextLoaderListener is configured with the contextConfigLocation <context-param>, and creates and manages the root WebApplicationContext.
The ServletDispatcherServlet is configured with the contextConfigLocation <init-param>, and creates and manages the servlet WebApplicationContext.
The root WebApplicationContext is the parent of the servlet appcontext, i.e any beans in the root WebApplicationContext are visible to those beans in the servlet WebApplicationContext.
Your first step should be to separate those configurations. With the correct beans in the correct places (e.g. all MVC stuff has to go in the servlet context). Do not share bean definitions between the two, it'll just get confusing and/or broken.
This doesn't answer your question directly, but I've always found it helpful to enable debug logging in Spring when I can't figure out what is going wrong.
Below are two that I commonly use in my logging.properties file:
org.springframework.beans.factory.support.level=FINEST
org.springframework.security.level=FINEST
Do you have more than one GET RequestMapping in your controller by any chance? If there are more than one and there is ambiguity in resolving them to a particular request Spring does not map to any of the ambiguous GET mappings.

Categories