James Sumners avatar James Sumners committed 634f885

Updated the skeleton to use Java based configuration instead of
XML based configuration.

Comments (0)

Files changed (8)

 # Overview #
 
-This is a simple skeleton project for a Spring WebMVC web application. It uses Maven to build the project.
+This is a simple skeleton project for a Spring WebMVC web application. It uses Maven to build the project. The configuration for the application uses as litle XML as possible. The primary configuration is done through standard Java.
 
 The project is configured to allow definition of properties files that will be parsed during build but not added to the final WAR package.
 
 2. Edit the `pom.xml` and change the "groupId", "artifactId", and "version" properties as desired.
 3. Rename `<project_root>/src/main/resources/project.properties` to match your artifactId. E.G. if you changed artifactId to "SuperCoolProject" then the properties file should be "SuperCoolProject.properties".
 	A. If you plan on using unit/whatever tests then you should do the same for `<project_root>/src/test/resources/project.properties`
-4. Edit `<project_root>/src/main/webapp/WEB-INF/web.xml` and adjust the "<display-name>" and "<servlet-name>" elements to your liking.
-	A. Adjust the `web.xml` under `<project_root>/src/main/webapp` if you care about testing.
-5. Rename `<project_root>/src/main/webapp/WEB-INF/springmvc-skel-servlet.xml` to match the servlet name in your `web.xml`. E.G. if you changed the "<servlet-name>" element value to "super-cool" then you would rename "springmvc-skel-servlet.xml" to "super-cool-servlet.xml".
-	A. Again, deal with the testing directory if you care about it.
+4. Edit `<project_root>/src/main/java/com/example/MyWebApplication/servlet/config/ContextConfiguration.java` to suit your needs.
+	A. Truly, you should be refactoring the "com/example/MyWebApplication" to your actual project package(s). But you should copy the "servlet/config/*.java" files to your package as a starting point for your configuation.
 
 ### Default Package ###
 
-The default project builds one controller that maps to `http://example.com/helloWorld` (where example.com is localhost or anything else). This controller is in the `com.example.MyWebApplication` package. As a result, `<project_root>/src/main/webapp/WEB-INF/springmvc-skel-servlet.xml` is set to scan `com.example.MyWebApplication` for annotated controllers. You should change this setting to match your project.
+The default project builds one controller that maps to `http://example.com/helloWorld` (where example.com is localhost or anything else). This controller is in the `com.example.MyWebApplication` package.
 
 ### Default Views Location ###
 
-The default project maps views to `/WEB-INF/jsp/` with a suffix of `.jsp`. You should adjust `<project_root>/src/main/webapp/WEB-INF/springmvc-skel-servlet.xml` to suit your preferences.
+The default project maps views to `/WEB-INF/jsp/` with a suffix of `.jsp`. You should adjust "ContextConfiguration.java" to suit your needs. Specifically, you need to adjust the `viewResolver` bean (or add more view resolver beans to the configuration).
     <war-plugin.version>2.3</war-plugin.version>
     <log4j.version>1.2.16</log4j.version>
     <slf4j.version>1.7.4</slf4j.version>
+    <javax.version>3.0.1</javax.version>
+    <cglib.version>2.2.2</cglib.version>
     <spring.version>3.1.4.RELEASE</spring.version>
   </properties>
 
     </dependency>
 
     <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>javax.servlet-api</artifactId>
+      <version>${javax.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
+      <version>${cglib.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-webmvc</artifactId>
       <version>${spring.version}</version>

src/main/java/com/example/MyWebApplication/ExampleApp.java

 import org.slf4j.LoggerFactory;
 
 import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.servlet.ModelAndView;
 
 @Controller
 public class ExampleApp {
   private static final Logger logger = LoggerFactory.getLogger(ExampleApp.class);
 
+  //
+  // This method adds an attribute to a framework passed in Model and
+  // simply returns the name of the view to load. This is the "easy way"
+  // of handling a request.
+  //
   @RequestMapping("/helloWorld")
-  public String helloWorld(WebRequest request) {
+  public String helloWorld(WebRequest request, Model model) {
     logger.info("/helloWorld -> " + request.toString());
 
-    // Do nothing except return the "view" name to load.
+    model.addAttribute("message", "Hello World");
+
     return "helloWorld";
   }
+
+  //
+  // This method creates, and returns, a ModelAndView object using a
+  // specific view (the same one as `/helloWorld`). This is the more
+  // pedantic way of handling a request. Note that the default ViewResolver
+  // is used by the ModelAndView constructor to determine the view to load.
+  // Thus, we simply need to specify the name of the view, not the full
+  // path.
+  //
+  @RequestMapping("/fooBar")
+  public ModelAndView fooBar(WebRequest request) {
+    logger.info("/fooBar -> " + request.toString());
+
+    ModelAndView mav = new ModelAndView("helloWorld");
+    mav.addObject("message", "FooBar");
+
+    return mav;
+  }
 }

src/main/java/com/example/MyWebApplication/servlet/config/ContainerInitializer.java

+package com.example.MyWebApplication.servlet.config;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.WebApplicationInitializer;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
+import org.springframework.web.servlet.DispatcherServlet;
+
+//
+// This class defines the configuration normally defined in a web.xml file.
+// Here, we manually load application context objects and the Spring dispatcher
+// object. This is more versatile than the web.xml file. For example, we can use
+// the JVM logger to log messages as we are preparing the web application.
+//
+public class ContainerInitializer implements WebApplicationInitializer {
+  private static final Logger logger = LoggerFactory.getLogger(ContainerInitializer.class);
+
+  @Override
+  public void onStartup(final ServletContext servletContext)
+    throws ServletException
+  {
+    WebApplicationContext applicationContext =
+      this.createContext(ContextConfiguration.class);
+
+    DispatcherServlet dispatcherServlet =
+      new DispatcherServlet(applicationContext);
+
+    ServletRegistration.Dynamic dispatcher =
+      servletContext.addServlet("dispatcher", dispatcherServlet);
+
+    dispatcher.setLoadOnStartup(1);
+    dispatcher.addMapping("/");
+  }
+
+  /**
+   * Factory method to create {@link AnnotationConfigWebApplicationContext} instances.
+   * @param annotatedClasses
+   * @return
+   */
+  private WebApplicationContext createContext(final Class<?>... annotatedClasses) {
+    AnnotationConfigWebApplicationContext context =
+      new AnnotationConfigWebApplicationContext();
+    context.register(annotatedClasses);
+    return context;
+  }
+}

src/main/java/com/example/MyWebApplication/servlet/config/ContextConfiguration.java

+package com.example.MyWebApplication.servlet.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.view.InternalResourceViewResolver;
+
+import com.example.MyWebApplication.ExampleApp;
+
+//
+// This class defines the normal "servletName-servlet.xml" configuration
+// (i.e. the webApplicationContext.xml). You can define all of the beans your
+// web application requires in this class, or, by virtue of the @EnableWebMvc
+// annotation, you can them up among multiple classes that have the
+// @Configuration annotation.
+//
+// Each bean defined in this configuration should be prefixed with @Bean
+// annotation.
+//
+// The @ComponentScan annotation tells Spring MVC to scan the listed package(s)
+// for classes marked with com.springframework.stereotype annotations. The
+// `basePackages` attribute is a comma separated list of packages to scan.
+//
+@Configuration
+@EnableWebMvc
+@ComponentScan (basePackages = {
+  "com.example.MyWebApplication"
+})
+public class ContextConfiguration {
+
+  //
+  // This bean defines the default view resolver. Since we have only defined
+  // the InternalResourceViewResolver it will always be used. This includes
+  // instances where you load a ModelAndView object yourself.
+  //
+  @Bean
+  public InternalResourceViewResolver viewResolver() {
+    InternalResourceViewResolver vr = new InternalResourceViewResolver();
+    vr.setPrefix("/WEB-INF/jsp/");
+    vr.setSuffix(".jsp");
+
+    return vr;
+  }
+}

src/main/webapp/WEB-INF/jsp/helloWorld.jsp

   <title>An Example View</title>
 </head>
 <body>
-  <h1>Hello world!</h1>
+  <h1>${message}!</h1>
 
   <c:forEach var="i" begin="0" end="5" step="1">
     <p><c:out value="${i}" /></p>

src/main/webapp/WEB-INF/springmvc-skel-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:p="http://www.springframework.org/schema/p"
-  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
-  http://www.springframework.org/schema/mvc/spring-mvc.xsd
-  ">
-
-  <!--
-    Enable scanning the classpath for annotated @Components to be used as
-    Spring beans.
-
-    The required "base-package" attribute is a comma separated list of Java
-    packages to scan.
-  -->
-  <context:component-scan
-    base-package="com.example.MyWebApplication"
-    />
-
-  <!--
-    Enables the use of the @Controller annotation.
-  -->
-  <mvc:annotation-driven />
-
-  <!--
-    Define a JSP resolver. When a request is made that resolves to a view
-    {viewname} then this resolver will look for {viewname}.jsp in the defined
-    location ("/WEB-INF/jsp/").
-  -->
-  <bean
-    id="jspViewResolver"
-    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
-    <property
-      name="viewClass"
-      value="org.springframework.web.servlet.view.JstlView" />
-
-    <property name="prefix" value="/WEB-INF/jsp/" />
-
-    <property name="suffix" value=".jsp" />
-  </bean>
-</beans>

src/main/webapp/WEB-INF/web.xml

   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
 
+  <!--
+    This is a bare bones web.xml file. It really isn't even necessary. The
+    actual configuration is done in the
+    com.example.MyWebApplication.servlet.config.ContainerInitializer.java file.
+  -->
+
   <context-param>
     <param-name>debug</param-name>
     <param-value>false</param-value>
   </context-param>
 
-  <servlet>
-    <display-name>SpringMVC Skeleton</display-name>
-    <servlet-name>springmvc-skel</servlet-name>
-    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
-
-    <load-on-startup>1</load-on-startup>
-
-    <!--
-    <init-param>
-      <param-name>contextClass</param-name>
-      <param-value>com.example.MyWebApplicationContext</param-value>
-    </init-param>
-
-    <init-param>
-      <param-name>contextConfigLocation</param-name>
-      <param-value>classpath:/WEB-INF/some-config.xml</param-value>
-    </init-param>
-
-    <init-param>
-      <param-name>namespace</param-name>
-      <param-value>springmvc-skel-servlet</param-value>
-    </init-param>
-    -->
-  </servlet>
-
-  <servlet-mapping>
-    <servlet-name>springmvc-skel</servlet-name>
-    <url-pattern>/</url-pattern>
-    <!--
-      You'd think you can map "/*" here but that causes much pain:
-      http://blog.anorakgirl.co.uk/2008/11/spring-web-mvc-and-url-mapping/
-      http://stackoverflow.com/questions/2129876
-    -->
-  </servlet-mapping>
-
   <welcome-file-list>
     <welcome-file>index.html</welcome-file>
     <welcome-file>index.jsp</welcome-file>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.