Loading...
Important Notice - Forums is archived

To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Product icon
TUTORIAL

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.

Spring integration helper class

Archie Cobbs
1 decade ago Feb 04, 2010 7:11pm
Valtteri Pirttilä
1 decade ago Feb 05, 2010 1:12pm
Archie Cobbs
1 decade ago Feb 05, 2010 4:04pm

Valtteri Pirttilä: You can autowire your Application class as your example shows, but how about other classes? In a large web app, you will no doubt have a lot of CustomComponents and other classes which you will need to autowire.

You just stick them in your application context... the same one (or a parent).

In other words, everything is setup just like a normal Spring MVC web application, with ContextLoaderListener, DispatcherServlet, etc. The AutowiringApplicationServlet just serves to connect your Application to the Spring context that it's already living within.

Here's the setup I'm using:

web.xml
  |
  +-- ContextLoaderListener
  |      |
  |      +-- applicationContext.xml      <-----+
  |           |                                |
  |           +-- Hibernate SessionFactory     |
  |           |                                |
  |           +-- DAO beans                 parent
  |           |                                |
  |           +-- Whatever other beans         |
  |                                            |
  +-- DispatcherServlet                        |
        |                                      |
        +-- dispatcher-servlet.xml       >-----+
              |
              +-- ServletWrappingController
              |     |
              |     +-- AutowiringApplicationServlet
              |          |
              |          +-- MyApplication
              |
              +-- SimpleUrlHandlerMapping
              |
              +-- Whatever other beans

This is the normal Spring MVC setup.

The Vaadin Application (MyApplication in the example) acts just like any other bean in the dispatcher-servlet.xml application context. Everything works just like a normal Spring MVC setup... which is the whole point, right?

Specifically, this kind of thing works:

public class HelloWorld extends Application {

    @Autowired
    private UserDAO userDAO;

    @Override
    public void init() {
        Window mainWindow = new Window("HelloWorld Demo");
        Label label = new Label("userDAO = " + this.userDAO);
        mainWindow.addComponent(label);
        setMainWindow(mainWindow);
    }
}

For completeness, here's some snippets from web.xml:

<!-- Spring context loader -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Spring dispatcher servlet -->
    <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>/myapp/*</url-pattern>
    </servlet-mapping>

and applicationContext.xml:

<!-- Hibernate session factory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
      p:dataSource-ref="dataSource" p:configLocation="classpath:hibernate.cfg.xml">

    <!-- Find DAO beans -->
    <context:component-scan base-package="com.example.dao.hibernate"/>

and dispatcher-servlet.xml:

<!-- Spring annotation support -->
    <context:annotation-config/>

    <!-- Vaadin application servlet -->
    <bean id="helloWorldController" class="org.springframework.web.servlet.mvc.ServletWrappingController"
      p:servletClass="com.example.AutowiringApplicationServlet">
        <property name="initParameters">
            <props>
                <prop key="application">com.example.HelloWorld</prop>
                <prop key="productionMode">true</prop>
            </props>
        </property>
    </bean>

    <!-- Map URIs to web controllers -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="urlMap">
            <map>
                <entry key="/hello" value-ref="helloWorldController"/>
                <entry key="/UIDL/**/*" value-ref="helloWorldController"/>
            </map>
        </property>
    </bean>

Again, this is all just the normal (to me anyway) Spring MVC setup.

Maury Hammel
1 decade ago Feb 06, 2010 5:09am
Maury Hammel
1 decade ago Feb 07, 2010 6:57pm
Archie Cobbs
1 decade ago Feb 07, 2010 8:24pm

Maury Hammel: I would still like to see your .xml files, though.

Sure.. I've built a little example project that builds a WAR file. See attachment to this post.

-Archie

Valtteri Pirttilä
1 decade ago Feb 08, 2010 6:47am
Maury Hammel
1 decade ago Feb 09, 2010 1:42am
Archie Cobbs
1 decade ago Feb 09, 2010 3:05pm

FYI,

The demo.zip that I uploaded demonstrates the Spring "MVC" approach using the DispatcherServlet, URL mappers, and Spring "controller" beans.

You can also do a simpler thing, which is to map the AutowiringApplicationServlet directly into your web.xml. With this approach, you still get your applicationContext.xml thanks to Spring's ContextLoaderListener, but there's no DispatcherServlet involved... and so your web.xml just looks like this:

<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_2_5.xsd"
  version="2.5">

    <display-name>Vaadin+Spring Demo #2</display-name>
    <description>Vaadin+Spring Demo #2</description>

    <!-- Spring context loader -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Vaadin servlet -->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.example.AutowiringApplicationServlet</servlet-class>
        <init-param>
            <param-name>application</param-name>
            <param-value>com.example.HelloWorld</param-value>
        </init-param>
        <init-param>
            <param-name>productionMode</param-name>
            <param-value>false</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

This eliminates the "extra hop" through the DispatcherServlet.

I've attached this even simpler example as demo2.zip.

-Archie

Petteri Torssonen
1 decade ago Feb 16, 2010 8:40pm
tom wang
1 decade ago Feb 24, 2010 5:12am
Petri Hakala
1 decade ago Feb 25, 2010 6:13am
Michael Chang
1 decade ago Mar 12, 2010 12:25am
Matti Lindell
1 decade ago Apr 26, 2010 7:33am

Thanks for the idea!

Here's the same for Portlet 2.0 env.

package foo.bar;

import javax.portlet.*;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.portlet.context.PortletApplicationContextUtils;

import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.AbstractApplicationPortlet;

public class AutowiringApplicationPortlet extends AbstractApplicationPortlet {
	private ApplicationContext springContext;
	private Class<? extends Application> applicationClass;
	
	@Override
	public void init(PortletConfig config) throws PortletException {
		super.init(config);
		springContext = PortletApplicationContextUtils.getRequiredWebApplicationContext(config.getPortletContext());
		
		final String applicationClassName = config.getInitParameter("application");
		if (applicationClassName == null) {
			throw new PortletException("Application not specified in portlet parameters");
		}
		try {
			applicationClass = (Class<? extends Application>) getClassLoader().loadClass(applicationClassName);
		} catch (final ClassNotFoundException e) {
			throw new PortletException("Failed to load application class: "+applicationClassName);
		}
	}
	
	protected ApplicationContext getSpringContext() {
		return springContext;
	}
	
	protected final AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws PortletException {
		try {
			return getSpringContext().getAutowireCapableBeanFactory();
		} catch (IllegalStateException e) {
			throw new PortletException("Containing context "+getSpringContext()+" is not autowire-capable", e);
		}
	}
	
	@Override
	protected Class<? extends Application> getApplicationClass() {
		return applicationClass;
	}
	
	@Override
	protected Application getNewApplication(PortletRequest request) throws PortletException {
		Class<? extends Application> clazz = getApplicationClass();
		try {
			return (Application) getAutowireCapableBeanFactory().createBean(clazz);
		} catch (BeansException e) {
			throw new PortletException(e);
		}
	}
}

And to portlet.xml

<portlet>
	<portlet-name>foo</portlet-name>
	<display-name>bar</display-name>
	<portlet-class>[b]foo.bar.AutowiringApplicationPortlet[/b]</portlet-class>
	<init-param>
		<name>application</name>
		<value>foo.bar.ApplicationClass</value>
	</init-param>
	<init-param>
		<name>widgetset</name>
		<value>com.vaadin.portal.gwt.PortalDefaultWidgetSet</value>
	</init-param>
	<supports>
		<mime-type>text/html</mime-type>
		<portlet-mode>view</portlet-mode>
	</supports>
	<supported-locale>en-US</supported-locale>
	<supported-locale>fi</supported-locale>
</portlet>
Tom Bruggeman
1 decade ago Jan 30, 2011 9:26am
Dmitry Katsubo
1 decade ago Jan 30, 2011 9:44pm
Charles Anthony
1 decade ago Jan 31, 2011 8:15am
Dmitry Katsubo
1 decade ago Jan 31, 2011 10:49am
Charles Anthony
1 decade ago Jan 31, 2011 11:30am
Archie Cobbs
1 decade ago Jan 31, 2011 3:03pm
Charles Anthony
1 decade ago Jan 31, 2011 4:19pm
Tom Bruggeman
1 decade ago Feb 01, 2011 7:05pm
Fabio Da Soghe
1 decade ago Mar 03, 2011 5:55pm
Fabio Da Soghe
1 decade ago Mar 03, 2011 6:11pm
Archie Cobbs
1 decade ago Mar 03, 2011 6:30pm
Archie Cobbs
1 decade ago Mar 03, 2011 6:33pm
Fabio Da Soghe
1 decade ago Mar 03, 2011 9:59pm
Archie Cobbs
1 decade ago Mar 04, 2011 1:05am
Fabio Da Soghe
1 decade ago Mar 04, 2011 8:45am
P P
1 decade ago Mar 06, 2011 10:50am
Fabio Da Soghe
1 decade ago Mar 07, 2011 12:46pm
Archie Cobbs
1 decade ago Mar 07, 2011 3:58pm
Dmitry Katsubo
1 decade ago Mar 07, 2011 4:13pm
Archie Cobbs
1 decade ago Mar 07, 2011 4:31pm
Fabio Da Soghe
1 decade ago Mar 09, 2011 8:20am
Matúš Ferko
1 decade ago Mar 09, 2011 1:31pm
Archie Cobbs
1 decade ago Mar 09, 2011 1:59pm
Matúš Ferko
1 decade ago Mar 09, 2011 3:57pm
Matúš Ferko
1 decade ago Mar 10, 2011 8:47am
Jorg Heymans
1 decade ago Mar 11, 2011 12:28pm