My controller class is in com.tps.sphbIntegration.controllers package
My applicationContext.xml file is in WEB-INF/spring/applicationContext.xml
In the controller class:
#Controller
#RequestMapping("jsp")
public class SpringController {
#RequestMapping(value="register.html" , method = RequestMethod.POST)
public String enterSucess(#Valid Login login , BindingResult result , Map model,HttpSession session){
if(result.hasErrors()){
System.out.println("Error happened...");
return "register";
}else{
System.out.println("I am an controller for get method of jsp/success.html ");
login = (Login) model.get("login");
session.setAttribute("empId", login.getEmpId()) ;
session.setAttribute("empName", login.getEmpName()) ;
session.setAttribute("empPassword", login.getEmpPassword()) ;
//session.setAttribute("empGender", login.getGender()) ;
//session.setAttribute("empType", login.getEmpType()) ;
ApplicationContext factory = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
EmployeeDao dao=(EmployeeDao)factory.getBean("d");
dao.saveEmployee(login);
return "registerCheck";
}
}
}
When execution I got the exception as
java.io.FileNotFoundException: class path resource [spring/applicationContext.xml] cannot be opened because it does not exist
Please help me to set the path of applicationContext.xml in the controller or give some example that how to access the applicationContext.xml in controller.
You have to tell the servlet context loader listener where to find your Spring application context XML files in the web.xml. Your error suggests to me that you didn't do that.
If you do have it in your web.xml, check the paths to see if they're correct.
If the paths are correct, open the WAR file and see if the XML is missing. Perhaps you have a deployment and packaging issue.
A web app should NOT be calling this:
ApplicationContext factory = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
This will work if there's a spring/applicationContext.xml in your WEB-INF/classes directory, but the preferred idiom is to use the ContextLoaderListener:
Use a ContextLoaderListener in accordance with DispatchServlet
You ought to be loading the application context for your entire app on startup, not for one controller and certainly not every time this URL is called by clients. Load it once on startup.
Your controller can implement BeanFactoryAware, an interface through which it will get access to the already existing instance of the application context. You must not create the application context yourself.
It is not quite clear from your code that you really need to access the context: it looks like you need the DAO injected into your Controller, through the standard dependency-injection mechanism of Spring.
I think this is the recommend way to gain access to the applicationContext:
#Autowired
private ApplicationContext applicationContext;
Dont need to use the "*Aware" classes this way.
no no no, you can do it like this!
as will, I see there is an ANNOTATION(#Controller) in your class,that means your class has been managed by spring, if you create another Application in your method,there is two instance of ApplicationContext in memory.
let your class implement the interface of ApplicationContextAware and override the method
setApplication,and add a private member ApplicationContext, and then assign the value in that method
Related
In the example below, is there a way to avoid doing a context.getBean()? All the other beans subsequently used by the testService get autowired. (It is a console application)
public class Test {
private static ITestService testService;
private static ApplicationContext context;
public static void main(String[] args) {
context = new ClassPathXmlApplicationContext(
new String[]{"/META-INF/spring/app-context.xml"});
ITestService testService = context.getBean(ITestService.class);
}
}
I tried adding autowire annotation to ApplicationContext, but it didnt work. Besides how does it know where my app-context.xml is located if I autowire it?
Update: I found what I needed over here
Right, you're missing out a few details here.
Below is a short explanation of how Spring works.
1- The application context is loaded somehow (we will get there soon).
2- After loaded, app context will initialize/create all beans defined. Here is when beans get injected as dependencies. After this Whenever you get a bean back from the app context, that bean is all initialized and ready to go with all the dependencies in place (considering everything went fine).
RE the first step, there are a few way to automate the Spring initialization.
One way is what you are doing, explicitly instantiating one. Other way could be via a context listener in case you're in a web environment, or maybe with the #RunWith. (You can find more here)
In your case, I believe you are looking for using Spring in a (Unit?!?) test environment so you are looking for something like
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class MyTest {
#Autowired
private ApplicationContext applicationContext;
// class body...
}
further details here
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#testing
You cannot call beans without initializing the application context first.
Secondly in your case Test class should be bean itself to be managed by spring then to autowire ITestService. The purpose of Application context as a container is to manage the bean lifecycle so u need to initialize it first by ClassPathXmlApplicationContextand then it will initialize all beans declared by you in ur xml file. About avoiding the getBean method if you are using servlets for creating web app you can avoid getBean. If not you should handle it manually.
I agree with what #Desorder has said. When I started working with #RunWith(SpringJUnit4ClassRunner.class) and #ContextConfiguration, I used to get my test cases working. But it took me some time to understand how these two are working internally and their default configurations.
If you would like to take some different approach and would like to try without #RunWith and #ContextConfiguration, take a look at the link - TUTORIAL: JUNIT #RULE. With this, you will be very clear which spring xml file locations are provided.
I am developing a spring MVC application. When I try to use AnnotationConfigApplicationContext in my controller class I am getting the following error. I have no idea what this statement exactly means.
#RequestMapping(value = "/generate", method = RequestMethod.POST)
public ModelAndView generateMappingFile(#ModelAttribute Mapping mapping)
{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
MappingFileGenerator mfg = ctx.getBean(MappingFileGenerator.class);
}
Error Message -->
java.lang.IllegalStateException:org.springframework.context.annotation.AnnotationConfigApplicationContext#116b3c0 has not been refreshed yet
Can someone explain me what went wrong here ? I am using Spring 4.0.1.. I am new to spring mvc.
When you are creating a new instance of an ApplicationContext (regardless which type) you are basically creating new instances of each and every bean configured in that ApplicationContext. That is nice the first time, it might work the second and depending on the amount of beans, the type of beans will crash after that. As the context will never be destroy (until the app crashed and is restarted) you will run into possible memory issues, performance issues, strange transactional problems etc.
A general rule of thumb is to never construct a new instance of an ApplicationContext but to use dependency injection instead.
If you really want access to the ApplicationContext put a field of that type in your controller and put #Autowired on it.
#Controller
public class MyController {
#Autowired
private ApplicationContext ctx;
….
}
Then you can do a lookup for the bean you need in the method. This can be handy if you use the ApplicationContext as a factory for your beans. If all the beans you need are singletons it is better to simply inject the bean you need.
#Controller
public class MyController {
#Autowired
private MappingFileGenerator mfg ;
….
}
Now Spring will inject the MappingFileGenerator and it is available for use in your methods. No need to create a new instance of an ApplicationContext.
More information is in the Spring Reference Guide.
#M.Deinum's comment will get quite a few more upvotes.
Think of creating a new ApplicationContext as instantiating a new (instance of an) application. Do you want to do that every time this (or any other method in said application) is called? No, you don't.
I'm guessing you think you do because you need access to your ApplicationContext in this method. To do that - i.e. to get access to the running application context (rather than creating a new one), you want to do
#Controller // or #Service / #Component / ... : tells Spring that this is a bean, and to inject the specified dependencies
class YourClass {
#Autowired // tells Spring that this object is a dependency should should be injected
ApplicationContext ctx;
#RequestMapping(value = "/generate", method = RequestMethod.POST)
public ModelAndView generateMappingFile(#ModelAttribute Mapping mapping) {
MappingFileGenerator mfg = ctx.getBean(MappingFileGenerator.class);
}
The key here is the Autowired annotation, which tells Spring to inject the annotated object as a dependency.
I highly suggest following the links I've included (for starters), as what you're doing here suggests pretty strongly that you haven't wrapped your head around what DI is and does for you, and until you do, using it is likely to be counterproductive toward it's own ends for you.
In case it helps someone, i was having this issue on a new URL Mapping added to a gradle project, i was missing the first slash of the url and that causing this "illegalstate not refreshed yet" on my tests
I've got a really annoying issue... I've not defined a Controller handler mapper and therefore I'm using the DefaultAnnotationHandlerMapping class. My issue seems to have something to do with the Controller bean name mapping to the Controller class e.g.
Incoming request to dispatcher -> index.htm
With the following Controller class:
#Controller
public class IndexController {
#RequestMapping(value = "/index.htm", method = RequestMethod.GET)
public String loginForm(ModelMap model) {
return "index";
}
}
Should map index.htm to indexController bean and then to IndexController class. I can see from the logs that Spring has registered the bean with the container however I get the following error:
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [xxx.controller.IndexController]
I know for certain that the class exists (because the bean name is derived from it).
The strange thing is that if I name my controller the same as the bean name (e.g. indexController) everything is fine!! (Obviously I don't want my classes to have a lower case first letter!!)
Just to note that I've used the following in my dispatcher-servlet.xml:
<mvc:annotation-driven />
<context:component-scan base-package="xxx" />
JLove
This error usually means your class has not been bundled in the war file. Unzip the war file and check your class is included correctly.
I suspect you successfully bundled "indexController.class" at some point, but prior packaging attempts failed. You haven't indicated how you are packaging your application, check your Maven/Ant configuration if you are using one of those. Beware of sharing build directories between IDE and build script, as they can occasionally conflict with each other.
I'd advice you to download STS and create new Spring MVC project template, to see, how Spring 3 MVC works.
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 trying to use a Json View for Spring (http://spring-json.sourceforge.net/) (org.springframework.web.servlet.view.json.JsonView) but whenever I write a controller class that extends AbstractController I get the following Error:
java.lang.IllegalStateException: ApplicationObjectSupport instance [org.springframework.web.servlet.view.json.JsonView] does not run in an ApplicationContext
The weird thing is, that when I implement the Controller interface directly and do not inherit, it is fine. The error only happens when I inherit from AbstractController.
In my current case though I would like to extend AbstractFormController and hence can't write a class that does not inherit from AbstractController.
Any ideas?
That's a rather misleading error message, it's actually complaining that the JsonView is not running inside an app context. What it means is that the JsonView bean was not instantiated by Spring, but that you instantiated it yourself (JsonView extends ApplicationObjectSupport, and should therefore be Spring-managed).
However, you haven't given us any of your code, so it's hard to tell for sure. I'm guessing your controller is instantiating JsonView itself? You need to let Spring do that, either by injecting a JsonView bean into the controller, or perhaps using a ViewResolver (if Spring-Json supplies one).
If you are doing Java configuration ( as opposed to XML ), in your configuration class you may want to call setApplicationContext method on object that is complaining.
This is what did the trick for me in Spring MVC 3.2.2 when trying to initialize ContentNegotiatingViewResolver in Java.
Here is the sample configuration class:
#Configuration
#EnableWebMvc
...
public class MyConfig
{
#Inject
private ApplicationContext appContext;
#Bean
public ContentNegotiatingViewResolver contentNegotiatingViewResolver ( )
{
ContentNegotiatingViewResolver retVal =
new ContentNegotiatingViewResolver( );
...
retVal.setApplicationContext( appContext );
return retVal;
}
}