About /WEB-INF/applicationContext.xml - java

This is driving me nuts. And this has been probably asked before but....
I've started recently with Tapestry for a Hibernate-Spring-Tapestry project. I used a maven archetype for Hibernate/Tapestry and then added Spring integration but this is giving more problems than I thought.
Currently I'm stuck with this, after adding the right tapestry-spring integration dependency and after changing the filter in /WEB-INF/web.xml I can't get jetty to run. This is because it can't find /WEB-INF/applicationContext.xml, mostly because I don't have that file in my project.
I just want to know what it should contain so I can move on to my next noob error.
EDIT: I've replaced the default Tapestry5 filter with
<filter>
<filter-name>app</filter-name>
<filter-class>org.apache.tapestry5.spring.TapestrySpringFilter</filter-class>
</filter>
Full web.xml -> http://pastebin.com/KgPTDrmC

TapestrySpringFilter works by retrieving the WebApplicationContext created and initialized by Spring's ContextLoaderListener (which you should also have). The applicationContext.xml file is a Spring XML bean declaration file which the ContextLoaderListener can use to create that WebApplicationContext.
The beans that go in it depend on your application.

Related

Different spring configuration files roles

I am developing my Spring-based web application using Spring Framework + Spring Security + Hibernate for data access (ORM) + Maven as build manager. All data acces operations must be provided by Hibernate.
My goal is to integrate Spring Security, Spring Framework and Hibernate for work together. I read many corresponding tutorials but what is confusing to me is that there are (in tutorials code) many xml-configuration files that missing in my project. Here is the structure of my project
As you can see there are only two Spring related xml-files and web.xml - they all been automaticaly generated by Spring when I added Spring Framework and Spring Security support to my project.
But in mentioned tutorials there are also files named "spring-database.xml", "spring-security.xml". The first as I think is to configure Spring toget data from database and the second is just basic Spring Security config. file.
Questions:
1) Those two files have not been generated automaticaly, even "spring-security.xml". Is it ok - is it like it must be? Or something wrong with my project settings?
2) If I can name those xml config files as I wish - then how does Spring know about them all and distinguish them? I just have not found anything about config files with such names in official Spring refference docs.
Answering question 2 please give some examples if it is possible.
3) My applicationContext file is empty - is it ok? And what if difference between it and dispatcher-servlet?
Thank you in advance!
1) I general you need just one spring configuration file, which is normally placed in src/main/resources (or elsewhere on the classpath) and after called applicationContext.xml or similar. If you use several Spring modules (such as Spring Data, Spring Security etc) it is common practice to have one separate config file for each module, but its not necessary, you can place all config in the same xml.
2) The naming doesn't matter, Spring looks in the classpath for the files: https://softwareengineering.stackexchange.com/questions/145545/where-to-put-spring-configuration-file
3) Normally the applicationContext.xml contains the definition of your beans and packages to scan for annotation and should be placed in src/main/resources. I guess dispatcher-servlet.xml is for the URI/servlet mapping (spring mvc)
There is no problem with your project structure. It is not mandatory to have the file names as you have in your project. If you want to have your own names for the xml files you have to mention the names of the xmls in the in web.xml. See below
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/dispatcher-servlet.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
Coming to the third question. applicationContext.xml should not be empty. You need to specify the beans of your application (services, dao, etc..) in applicationContext.xml. In dispatcher-servlet.xml you need specify beans (handler mappings, controllers, view resolvers etc..) related to spring mvc.

WEB-INF/myproject-servlet.xml versus WEB-INF/web.xml

I spent few days fixing bugs in my Spring project. For really long time, my main problems in error log were:
Bean already exists
I have got two files:
WEB-INF/myproject-servlet.xml
WEB-INF/web.xml
in first one, I can put following input (let's assume I have got an application to manage animals in zoo):
<context:component-scan base-package="com.my.package.animals" />
with that (as well as I understand) we are enabling Spring beans auto-discovery. So now, when we run our application, Spring will take all classes from this package, later it will go through all config files in resources directory and will inititliaze all beans (placed in config files, which are associated with a given package).
The second one, web.xml includes lines like this
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myproject-servlet.xml</param-value>
</context-param>
I can also put path to my config files, for instance:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:animals-config.xml</param-value>
</context-param>
So now, I have 'auto-detecting' in myproject-servlet.xml and I have got context-param in web.xml for the same objects.
My question is, is it possible, that errors "Bean already exists" are coming from this? I am almost sure that yes, I checked all beans ids and there is no duplicates.
So I have another question. What is a good approach of doing that? When I create new config file, where I should inform my application about that? In myproject-servlet.xml or web.xml. I really need to clean up my application and I will start with that.
I checked some examples and people rather do not put more than one <context-param> in web.xml file Simple example
Thank you in advance
Ok, I am really close to solve my problem.
Let's assume I have got two packages:
com.my.pckg.a
com.my.pckg.b
with classes
com.my.pckg.a.ClassA
com.my.pckg.b.ClassB
I added in myproject-servlet.xml following line:
<context:component-scan base-package="com.my.pckg.a" />
I have got a config file myconfig.xml and inside I have got beans based on classes ClassA and ClassB.
Let's say we have got beans with ids as follows:
ClassA: ida1, ida2
ClassB: idb1, idb2
So, I am running my jetty server and the question is:
Which beans will be initialized? I declared only package com.my.pckg.a, so from myconfig.xml, spring should load only ida1 and ida2 but this file includes also beans for another class.
So finally... ?
Finally, I suppose I find a problem. In web.xml file I have got a line:
<context:component-scan base-package="com.dirty.pckg" />
in this package I have got a class DirtyClass with #Controller annotation. One of the fields of this class is:
private static ApplicationContext context = new ClassPathXmlApplicationContext("dirty-config.xml");
So, when my application is getting up, Spring takes DirtyClass (because it has #) and maps it. Because os static modifier of context it triggers reading dirty-config.xml. That's way I could not understand why my code behaves in strange way.
The web.xml file is the configuration of your web application. It is not related to Spring.
The contextConfigLocation context-param is the one spring listener use to search for Spring configuration files. It is spring related.
You can have multiple spring configuration files that you register in your web.xml but these files must not define the same bean (bean id must be different). You can also have only one spring configuration file that will it self include other configuration files as described here : http://www.mkyong.com/spring/load-multiple-spring-bean-configuration-file/
Answer to the other question :
When you added the component scan, you ask spring to scan the package com.my.pckg.a for annotation like #Service, #Component, ... The component scan is not a filter for the rest of the configuration it is a configuration itself. So the fact that you added component scan, will not change the behaviour of myconfig.xml. Both ida1, ida2 and idb1, idb2 will be instanciated.
I don't really get what you are trying to accomplished with your configuration files. Maybe if you explain your needs, we could help you set up the right config for you.
web.xml is configuration file. It has classes(like listeners, filters,filter-mapping, servlet,servlet-mapping), resources and configuration(like context param, diplayname, error-page, session-config) of the application and how the web server uses them to handle web requests. When the web server receives a request for the application, it uses web.xml to map the URL of the request to the code that is supposed to handle the request.
Coming to what should be in web.xml and what should be in myproject-servlet.xml:
1)In Spring, ApplicationContext can be hierarchical. One ApplicationContext can have multiple child ApplicationContexts and can only have one parent. Beans in child ApplicationContext can access the beans in parent.
2)DispatcherServlet dispatches requests to handlers(controllers), with configurable handler mappings, view resolution configuration(what view template you use for the application for example jsp).
Keeping the two points in mind, our web.xml should be like:
<!--Root web application context(Parent context) - beans for service or persistence layer should be in this -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:service-layer-beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<!--DispatcherServlet loads its configuration into its own context(chile context) and refers Root web application context as a parent, so it have access to beans in parent context and can override it but not vice versa.-->
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myproject-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>

how to include a spring project into another spring project

I am new to spring and currently struggling in understanding the settings required for using an existing spring project in my current project
I have a spring project which has all the service for communicating with the database and webservice.
I am writing a new application which neeeds to talk to the database and webservice.
I thought of re-using the existing implementation in the other project.
I included the project in the build path of the current project.
However I am getting dependency injection error.
Now I am kind of stuck to see what all the other files I need to have in my current project settings so that I can re-use the existing project.
Should I need to import the context file of the other project in to my current one? If so can someone point me to the documentation where I can refer for some guidance?
I'll give it a shot. Hope I can bring about clarity to your question... =D
When you say "I included the project in the build path of the current project.", I assumed you added a spring web project as a dependency to another spring web project. In summary, you can't add a spring web project as a dependency of another spring web project. Let's take some time to understand how you wire a bean to do injection in spring container first...
When you use spring framework, you will find a similar code in your web.xml like the following:
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
What you have just done is to use spring framework's servlet to handle every request URL that ends with .htm. Of course you may configure it otherwise.
You should also have another xml that contains all your bean tags. By default, it is spring-servlet.xml. In this spring-servlet.xml, you specify which bean shall be injected to which bean if you are going the xml configuration approach. If you are using annotation approach, you should have a tag to scan all your existing #Component (and its derived annotations) annotated classes, then use #Inject or #Autowired annotation to inject the declared instance(bean). For example:
<context:component-scan
base-package="org.companyname.webappname" />
<context:annotation-config />
So far, what I have been explaining is how to declare a bean in a spring container. An "injection" happens only when you declare a bean (to live in spring container when web server starts) in a spring container, and specify which class it should be injected into.
So now that you have two spring web projects (assumption), with two web.xml and two spring container, you will have a problem getting the base-project's spring container to find the dependent spring web project's packages/classes. I suggest you move all the classes in the dependent project into the base-project and only have one spring container (one web.xml).
Another way is to create a Java Library Project, place all your services, DAO and web services classes in it and build it as jar. In your base project, add the jar file (as dependencies) and either do a component-scan on the jar's package or declare it in xml with the jar's package. Either way, you should only have one spring container, one web.xml.
Hope I am not confusing you.
You got to understand how the IoC container work first. Here is where you need to read and digest how spring IoC works: http://docs.spring.io/spring/docs/3.0.x/reference/beans.html
Update: if you are doing a non web spring project, the concept of having only one spring container still stands. The solution of moving dependent project's classes to a jar file is still valid. Except that you don't configure spring via web.xml. =D
You need to import the file containing the bean definitions of the service layer(say, service-context.xml) into the new project.
It can be done as:
<import resource="classpath:service-context.xml"/>
It depends on how you have setup the project.
In general you would need to use
An example of this can be seen here (see the directions on how to include the project in your own application)

Spring 3 Application Context loading

I am a bit familiar with Spring framework but am still having lots of question concerning use of spring from project architectural view point. Now I am setting up Spring 3 and a Maven web application and am willing to try out all the the fancy component-scan's and autowiring features however this is where I get confused.
I am trying to break the project into sub-modules. And at some point these sub-modules may include something-context.xml in classpath*:resource/META-INF, like for instance when I will want to define a datSource related stuff in a separate module. So that's fine spring let's you load context files from within class-paths of all of the jars.
But here is where it gets vague - say I am using component scan. I am obviously using spring DispatcherServlet and it needs a servlet context to be loaded, and then there is a global application context parameter specified in web.xml contextConfigLocation.
So now servlet context config has a component-scan feature enabled for com.mycom.project.controllers and context loaded in the global contextConfigLocation has a context loaded with component scan feature for package com.mycom.project also searches for classpath*:META-INF/spring/*-context.xml.
So my question is - does this load controller's twice given that component scan is used for a for com.mycom.project.controllers and com.mycom.project? Or is it all loaded into one huge container and the contextConfigLocation parameter for either DispatcherServlet or global declaration is sort of access issue ? As in DispatcherServlet will reach only what's defined in servlet-context.xml but won't be able to use anything else?
And if my assumption is wrong, could I have a suggestion on how to manage multi-module project issues?
Thanks.
Yes, you might run into trouble. See this link for how to solve your problem.
#Service are constructed twice
The way you proceed when creating modules seems valid to me. You have a context.xml file for each module and all will get loaded once you load the application. Your modules are self-contained and can also be used in different environments. That's pretty much the way I'd also do it.

using quartz in a web app with spring

I've created a small console application to see how quartz work and it was easy to create an applicationcontext object inside the main method to get the cron run. OK now I'm in a real project managed by maven and which is using cron jobs defined in some of the modules. Each of the module has his own spring config file. I had 3 of the modules using quartz so it was setup in each of the spring config file. The web app module is the one who has the dependency of each of the modules.
Now i had few concerns:
should I created the applicationcontext as in the console project or it's supposed to be loaded. If yes, where am I supposed to load it.
based on research on the Internet I did on line I use MethodInvokingJobDetailFactoryBean for easy unit testing. And now that I have to use the CronExpression class to test the getNextValidTimeAfter, I still don't know how to organize it properly
Can anyone give me a hand. I'd really appreciate it. Thanks for reading
As per comment, the question is closer to "How to load Spring application context file(s) for a Web application".
According to Section 3.8.5, "Convenient ApplicationContext instantiation for web applications", you can register an ApplicationContext using the ContextLoaderListener as follows (add this to your web.xml file):
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- or use the ContextLoaderServlet instead of the above listener
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
-->

Categories