Is there a way to develop portlets with spring without using the DispatcherPortlet? I want to use other technologies for the UI, mainly Vaadin. Spring is used for DI and other stuff. Is there something similar to ContextLoaderListener class in the Portlet side?
Looking at the Spring documentation: You can create an ApplicationContext as follows:
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
Referencing xml files on your classpath.
You can then get beans by calling context.getBean("beanName"). No need for Spring MVC.
I was hoping for a more detailed answer than what Noel gave. Maybe there is some best practice to this? Here is my current solution:
Give the xml file locations as a init parameter to my portlet.
My init method looks something like this
#Override
public void init(PortletConfig config) throws PortletException {
super.init(config);
String configLocations = config.getInitParameter("contextConfigLocation");
ClassPathXmlApplicationContext springContext = new ClassPathXmlApplicationContext();
springContext.setConfigLocation(configLocations);
springContext.refresh();
config.getPortletContext().setAttribute(APPLICATION_CONTEXT_ATTRIBUTE, springContext);
}
Now I can access my applicationContext through PortletContext every time I need.
(ApplicationContext) portalContext.getAttribute(APPLICATION_CONTEXT_ATTRIBUTE);
APPLICATION_CONTEXT_ATTRIBUTE is just string constant that I made up. I'm still open for better solutions.
You can use PortletApplicationContextUtils to retrieve the web application context:
ApplicationContext ctx = PortletApplicationContextUtils.getWebApplicationContext(getPortletContext());
Then you just need to add some configuration on your web.xml.
Related
I'm trying to setup a Web application with Spring 4.1 and Wicket 6.18. I want to use the full code approach. I have two test classes annotated with #Configuration and with #Bean. I want them to be discovered when i startup my app in Tomcat but it is not working unless i manually scan the base package in my custom WebApplicationInitialzer. By manually i mean to invoke AnnotationConfigWebApplicationContext.scan().
I looked through quite a few tutorials about the code based approach and didn't saw they do this. Even in the official spring docs they don't do this.
What i'm doing wrong that i need this and how to correct it?
My custom WebApplicationInitialzer looks like this:
public class WebAppInitializer implements WebApplicationInitializer {
private static final Logger logger = LoggerFactory.getLogger(WebAppInitializer.class);
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
container.addListener(new ContextLoaderListener(context));
context.scan("pl.myhouse"); //why do i need this???
FilterRegistration filter = container.addFilter("wicket.myproject", WicketFilter.class);
filter.setInitParameter("applicationClassName", WicketApplication.class.getName());
filter.setInitParameter(WicketFilter.FILTER_MAPPING_PARAM, "/*");
filter.addMappingForUrlPatterns(null, false, "/*");
}
}
You both #The Head Rush and #Aeseir are correct. I was missing the rootContext.register(Appconfig.class) as well as the #ComponentScan. I even could share my knowledge further: Configuring Spring Wicket using Java Conf instead of xml :)
My colleagues very often use word "application context". In many articles this collocation used very often too.
My current understanding: application context is single xml file.
But I understand that if I was right, people wouldn't use "application context" instead of configuration xml file.
Can you help me to deal with this issue?
#feak gives a straight answer about the meaning of ApplicationContext in terms of Spring. In short, it is an object that loads the configuration (usually a XML file annotation based) and then Spring will start managing the beans and its benefits:
Beans declared in package
Beans declared by annotations
Constructor and method autowiring
Bean injection
Configuration, .properties and .yaml file loading
etc
To start an application context, you may use one of the following:
Manually load the application context at the beginning of your application. This is done for sample purposes or in standalone applications:
public class Foo {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
//use the context as you wish...
}
}
In case of Java web applications using Spring MVC, the DispatchServlet will load the application context for you, so you only have to create a springapp-servlet.xml file in WEB-INF folder of the application.
Note that an application context is associated to a single configuration (XML based or not). Period.
After understanding this, you could also understand that you can have more than a single application context per application. This is, having two or more ApplicationContexts in the same application. From the last example in the console application, this is easy to check:
public class Foo {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
ApplicationContext context2 =
new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
//use the context as you wish...
}
}
Note that we have two application contexts using the same XML configuration. Can you do this? Yes, you're actually seeing it here. What's the difference, then? The main difference is that Spring beans singleton scopes are singleton per application context, this mean when retrieving a Bar bean that's configured in applicationContext.xml file from context will not be the same as retrieving it from context2, but several retrieves from context will return the same Bar bean instance.
Is this considered a good or bad practice? Neither, it will depend on the problem to be solved (in case of last example, I would say it is a bad practice). Most people would recommend having all your beans configured in a single place (via XML or another) and loaded by a single application context.
Let's understand this in simple words.
The ApplicationContext is the central interface within a Spring application that is used for providing configuration information to the application. It's created when the application starts running.
It provides the entire configuration needed by our application:
Bean Factory - Responsible for creation of java objects called beans. One example is components in the application.
Application listeners - all listeners needed for events.
WebServer information.
Application current environment specific information.
Resource pattern resolver - resource loader with path matcher.
Life cycle Processor.
Class Loader.
Start and shutdown monitor.
Servlet Context.
Reader and Scanner.
Logger
etc.
package com.srmhitter9062.spring;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext ctx;
#Override
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
ctx = appContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
}
We can get some idea about the Application object in below snapshot.
In summary, we can say the Application context is a Configuration object created for application to run.
The applicationContext.xml defines the beans for the "root webapp context". It's a web aware ApplicationContext.
It is used to have beans that are shared between all servlets in a web application.
I hope this is helpful.
I guess that you colleagues meant the loaded spring application context, which allows access to:
configuration of application,
initialized beans,
application events api,
etc
From the javadoc:
Central interface to provide configuration for an application. This is
read-only while the application is running, but may be reloaded if the
implementation supports this.
An ApplicationContext provides: [...]
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
I'm new to the Spring Framework. We want to introduce it (3.1) in a web application, currently using struts in the web layer, service facades and business objects in the business layer and self-written JDBC DAOs in the persistence layer (all of it closely coupled!)
I created several .xml configurations, one for the servlet config, scanning the com.mydomain.web package only. Another one on the service layer appContext-service.xml which scans com.mydomain.bs and .bo packages and one for the DAO layer appContext-persistence.xml scanning the .dao package.
We have four Eclipse projects with appropriate project dependencies: Web, Business, Common (contains domain objects, DTOs, Exceptions, etc), DataAccess.
I want to use annotations where possible and already created a MVC controller, a new service with interface and a new dao with interface, using the JDBC template, which all works great.
Now my questions are:
We can't re-write all the code at once, we're talking about a larger code base here. But what do I do, when the newly created service is also needed from services and business objects that are not (yet) Spring aware? They're not beans or not being created by Spring. How would I get hold of my service bean?
We have several standalone applications for batch processing, cleaning up the file system and database tables periodically, etc. They're triggered by cron (UNIX cron) and therefore have their own JVM. How would I best use Spring services here, given the different .xml configurations?
Does my setup make any sense at all?
Thanks for any insight.
It's very common that one let spring handle the lifecycle of all the beans, otherwise it might get a bit tricky. The objects that are not spring beans are hopefully initialized somewhere. Make that initializer a spring bean and make it application context aware
public class SpringContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void init(){
ServiceBean1 srv1 = (ServiceBean1)applicationContext.getBean("serviceBean1");
myNonSpringObject.setService1(srv1); // Or something
}
}
Setting up a standalone spring app is very easy. Just create a Spring XML and wire your beans (either via scanning/annotations or XML). It is not really recommended to do this in the main method, but you could easily figure out how to get this setup in your standalone application. Keep in mind that your application itself should not really do much lifecycle logic but let Spring do that.
public class StandaloneSpringApp{
public static void main(String[] args){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
SomeBeanType bean = (SomeBeanType)ctx.getBean("SomeBeanName");
bean.doProcessing(); // or whatever
}
}
Your setup makes perfect sense, even though I cannot visualize your entire scope, your approach is a good starting point for a large modularized spring application.
When I previously developed servlet applications without Spring, I could read configuration parameters like this in my servlet:
#Override public void init() throws ServletException {
ServletContext sc = getServletContext();
String someSetting = sc.getInitParameter("someSetting");
}
However, I'm developing an application with Spring MVC now, which means I no longer have a servlet myself, but use Spring's DispatcherServlet.
Now, how can I access those init parameters in spring-servlet.xml to pass them to one of my beans?
I'm using Spring 3, and am a n00b with it. Every time I see a bean without an id, my mind flips XD
I guess you can #Inject a ServletContext in your controllers, and take the params from there.
Of better, use #Value together with a specificPropertyPlaceholderConfigurer. See this answer
Do you really need these to be init-parameters in the Servlet context?
In Spring you can just inject values into your beans from a properties file using PropertyPlaceholderConfigurer.