Spring Security 6 and JSP view rendering - spring-mvc

I'm upgrading an application from Spring Boot 2.7 to Spring Boot 3 which includes updating to Spring Security 6.
We have the following properties set:
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
We use JSPs as a template language, where the controller returns the view file name e.g.
#RequestMapping("/")
public String home() {
return "home";
}
This will render the JSP page /WEB-INF/view/home.jsp
The security config is e.g.
#Configuration
public class SecurityConfig {
#Bean
public SecurityFilterChain config(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((auth) -> auth
.requestMatchers("/").permitAll()
.anyRequest().authenticated()
);
}
Since upgrading, visiting localhost/ redirects the browser to localhost/WEB-INF/view/home.jsp and this returns a 403 because access to that page isn't permitted.
If I allow access to this with .requestMatchers("/", "/WEB-INF/**").permitAll() it works OK (i.e. stays on / and renders the JSP page) but this seems like a bad idea, and an unnecessary step.
With debug logging on, Spring logs the following:
DEBUG [requestURL=/] o.s.security.web.FilterChainProxy : Securing GET /
DEBUG [requestURL=/] o.s.security.web.FilterChainProxy : Secured GET /
DEBUG [requestURL=/] o.s.security.web.FilterChainProxy : Securing GET /WEB-INF/view/home.jsp
DEBUG [requestURL=/] o.s.security.web.FilterChainProxy : Secured GET /WEB-INF/view/home.jsp
I cant' see anything in Spring Security migration guide about this, does anyone know what is going on?
Update
I've isolated this into a clean example:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>jsptest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jsptest</name>
<packaging>war</packaging>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Application.java
#SpringBootApplication
#Controller
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public SecurityFilterChain config(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/", "/WEB-INF/view/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
#RequestMapping("/")
public String home() {
return "home";
}
}
src/main/resources/application.properties:
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
src/main/webapp/WEB-INF/view/home.jsp:
hello

Something I've overlooked first as well.
In spring security 6, forwards and includes are part of the security filter by default.
See https://docs.spring.io/spring-security/reference/5.8.0/migration/servlet/authorization.html#_permit_forward_when_using_spring_mvc
Allowing forwards globally can be done through this additional line in security configuration.
.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()

Related

Newb pact JVM provider

Hope someone might be able to help me, been beating my head against the wall for a while and can't seem to break through. I have tried following multiple examples and doing endless searching, just can't seem to find out what I am missing. There are a lot of examples to follow but most are spring applications and I know nothing about spring so I don't know if I am trying to mix spring with non-spring code...
This is NOT a spring application nor do I want it to be. I am trying to get this going as just a simple java producer verification. Pretty much as simple as it can be...
I have a good contract and I am able to get a successful verification of the contract using JS but want to use JAVA.
I have way too many imports in my code but don't know at this point which ones are not important and or are duplications.
I have a few compile errors but can't seem to find out how to resolve. I noted the compile errors in the code. I think I am close but just don't know at this point.
Is the pactTestTemplate method the one that actually does the contract verification? So that is the method I would call from my unit test? Really confused at this point as to all the magic that is going on in the background...
If you made it this far, thanks...
package testWorkContract;
import au.com.dius.pact.provider.junit.PactRunner;
import au.com.dius.pact.provider.junit.Provider;
import au.com.dius.pact.provider.junit5.*;
import au.com.dius.pact.provider.junit5.PactVerificationContext;
import au.com.dius.pact.provider.junit5.PactVerificationInvocationContextProvider;
import org.junit.jupiter.api.extension.*;
import org.junit.runner.RunWith;
import au.com.dius.pact.provider.junit.loader.PactFolder;
import au.com.dius.pact.provider.junit.loader.PactUrl;
import au.com.dius.pact.provider.junit.target.HttpTarget;
import au.com.dius.pact.provider.junit.target.Target;
import au.com.dius.pact.provider.junit.target.TestTarget;
import org.apache.http.HttpRequest;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.runner.RunWith;
import au.com.dius.pact.provider.junit.*;
#PactFolder("/temp/pacts")
#RunWith(PactRunner.class) // Say JUnit to run tests with custom Runner
#Provider("work") // Set up name of tested provider
public class PactProvider {
#TestTarget // Annotation denotes Target that will be used for tests
public final HttpsTestTarget target = new HttpsTestTarget("127.0.0.1", 443);
#BeforeClass // Method will be run once: before whole contract test suite
public static void setUpService() {
}
#Before // Method will be run before each test of interaction
public void before() {
}
// JUST A QUICK TEST METHOD TO MAKE SURE MY UNIT TEST CAN WORK...
public int testService() {
return 0;
}
#TestTemplate // THIS IS AN ERROR, CAN'T FIND #TestTemplate
#ExtendWith(PactVerificationInvocationContextProvider.class)
void pactTestTemplate(PactVerificationContext context, HttpRequest request) {
context.verifyInteraction();
}
}
Here are my dependencies, first time setting up maven also so there might be problems there:
<properties>
<json-schema-validator.version>3.3.0</json-schema-validator.version>
<junit.jupiter.version>5.5.2</junit.jupiter.version>
<pact.version>4.0.10</pact.version>
<maven.surefire.version>3.0.0-M5</maven.surefire.version>
</properties>
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.3.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-consumer-junit5</artifactId>
<version>${pact.version}</version>
</dependency>
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-provider-junit</artifactId>
<version>${pact.version}</version>
</dependency>
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-provider-junit5</artifactId>
<version>${pact.version}</version>
</dependency>
</dependencies>
I was able to get past my problems. I was thinking about this incorrectly. The code I was trying to write SHOULD HAVE BEEN THE ACTUAL JUNIT test. I was trying to write a junit test that then called the class I was trying to put together.
This is the junit test I ended up with for starters
package testWorkContract;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testng.annotations.Test;
//import au.com.dius.pact.core.model.annotations.PactFolder;
import au.com.dius.pact.provider.junit.loader.PactFolder;
import au.com.dius.pact.provider.junit.Provider;
import au.com.dius.pact.provider.junit.loader.PactSource;
import au.com.dius.pact.provider.junit5.HttpsTestTarget;
import au.com.dius.pact.provider.junit5.PactVerificationContext;
import au.com.dius.pact.provider.junit5.PactVerificationInvocationContextProvider;
import junit.framework.Assert;
#Provider("work")
#PactFolder("/temp/pacts")
public class PactProviderTest {
#BeforeEach
void before(PactVerificationContext context) {
// context.setTarget(HttpTestTarget.fromUrl(new URL(myProviderUrl)));
// or something like
context.setTarget(new HttpsTestTarget("localhost", 443, "/", true));
}
#Test
#TestTemplate
#ExtendWith(PactVerificationInvocationContextProvider.class)
void pactVerificationTestTemplate(PactVerificationContext context) {
context.verifyInteraction();
}
}
and this is the pom file
<properties>
<json-schema-validator.version>3.3.0</json-schema-validator.version>
<junit.jupiter.version>5.5.2</junit.jupiter.version>
<pact.version>4.0.10</pact.version>
<maven.surefire.version>3.0.0-M5</maven.surefire.version>
</properties>
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.3.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-consumer-junit5</artifactId>
<version>${pact.version}</version>
</dependency>
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-provider-junit</artifactId>
<version>${pact.version}</version>
</dependency>
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-provider-junit5</artifactId>
<version>${pact.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
<plugin>
<groupId>au.com.dius.pact.provider</groupId>
<artifactId>maven</artifactId>
<version>4.1.11</version>
<configuration>
<serviceProviders>
<!-- You can define as many as you need, but each must have a unique name -->
<serviceProvider>
<name>work</name>
<!-- All the provider properties are optional, and have sensible defaults (shown below) -->
<protocol>https</protocol>
<host>localhost</host>
<port>443</port>
<path>/</path>
<insecure>true</insecure>
<pactFileDirectories>
<pactFileDirectory>/temp/pacts</pactFileDirectory>
</pactFileDirectories>
</serviceProvider>
</serviceProviders>
</configuration>
</plugin>
</plugins>
</build>

Controller class is not getting provoked in Spring MVC

Spring MVC Controller class is not working and throwing 404.
In application I created an entity and added all the credentials of my MS-SQL database. However, after staring the app and hitting the submit button the app is landed to 404 and controller is not provoked and entity is not created as well.
index.jsp is as follows:
<form action = "/save" method = "post">
ID: <input type = "text" name = "uid">
<br />
Name: <input type = "text" name = "name" />
<input type = "submit" value = "Submit" />
</form>
Controller class is as follows:
#Controller
public class MyController {
#Autowired
public EmployeeDao empDao;
#RequestMapping("/save")
#ResponseBody
public String save(Employee emp){
System.out.println("Here");
empDao.saveEmployee(emp);
return "success";
}
}
The Entity Class:
Entity
#Table(name="employee")
public class Employee {
#Id
private int uid;
private String name;
}
The context class:
#Bean
public DriverManagerDataSource getDataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
ds.setUrl("jdbc:sqlserver://localhost:1433;databasename=cruddb11;integratedsecurity=true");
ds.setUsername("ABCD");
ds.setPassword("00000");
return ds;
}
The Pom:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.websparrow</groupId>
<artifactId>spring-mvc-fetch-data</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- Hibernate Core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.17.Final</version>
</dependency>
<!-- Hibernate Validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.0.Alpha5</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.0.2.Final</version>
</dependency>
<!-- spring mvc dependency -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- spring jdbc dependency -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>6.2.2.jre8</version>
</dependency>
<!-- mysql databse connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
This will not work as you expect.
1.) This is not neccessary but helpful if you have more than one leading part in your url. Annotate your class with the #RequestMapping Annotation. Like this:
#RequestMapping(value="/fileoperations") // Then you don't need the leading slash in the method
#Scope(value="session")
Use the second line if you are using sessions e.g. with Tomcat.
2.) The form only contains the variables uid and name so you must query them as parameters to work with in your controller.
3.) And also you must tell your controller to use the right Requestmethod. Like this:
#RequestMapping(value="save", method=RequestMethod.POST)
public #ResponseBody String save(
#RequestParam String uid,
#RequestParam String name) {
System.out.println("Here");
// Maybe you should load the Employee first before updating it.
Employee emp = this.empDao.readEmployee(name);
if (emp != null) {
emp.setUID(uid);
emp.setName(name);
this.empDao.saveEmployee(emp);
return "success";
} else {
return "error: no employee here by that name";
}
}
Change your save method signature to following, annotating Employee parameter with #ModelAttribute
#Autowired
public EmployeeDao empDao;
#RequestMapping("/save")
#ResponseBody
public String save(#ModelAttribute Employee emp){
System.out.println("Here");
empDao.saveEmployee(emp);
return "success";
}
You had better change #RequestMapping to #Post.

Spring EhCache configuration - Cannot find class [org.springframework.cache.ehcache.EhCacheManagerFactoryBean]

I need help with ehCache configuration.
These what i did :
ehcache.xml inside my src/main/resources folder
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="allNodesCache"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300" timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
ehCache configuration inside my applicationContext-web.xml
<!-- ehCache configuration -->
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/>
<!-- EhCache library setup -->
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="ehcache.xml"/>
pom.xml:
<!-- ehCache -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.7.2</version>
</dependency>
My repository class:
#Repository
public interface NodeRepository extends JpaRepository {
#Cacheable(value = "allNodesCache", key = "#node")
#Query("select new com.datum.fnd.domain.Node(c.idNode, c.name, c.address, c.description, c.point) from Node c")
I got message like this :
Cannot find class [org.springframework.cache.ehcache.EhCacheManagerFactoryBean] for bean with name 'ehcache' defined in ServletContext resource [/WEB-INF/spring/applicationContext-web.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.cache.ehcache.EhCacheManagerFactoryBean
Add the spring context support dependency to your classpath:
https://mvnrepository.com/artifact/org.springframework/spring-context-support

Wrong context used to inject dependency in environment with servlet- and portlet-context

I am currently working on an application, that is accessed as both a portlet and a servlet (at least some parts are). I am also using compile-time-weaving to inject dependencies into beans in the prototype scope, so for example beans that are created via "new" or more commonly via Hibernate, as described here: http://www.chrissearle.org/node/285
This is working fine so far, however I am now using a server-api that has to be called differently in servlets and portlets. So I created an interface for a service in my application, and two implementations to the interface, one for servlets and one for portlets, so each can use the server-api differently. Each implementation is configured only in the coresponding servlet/portlet-application-context.
If the servlet is used first, this works fine, the service-implementation for the servlet is injected and used. However, once the portlet is used, only the service-implementation for the portlet will be injected and used, for both the portlet and the servlet.
I would have expected the containers for servlets and portlets to be separate. Is this an error or not supported by Spring, or is there a way to fix or work around this? The application is still using Spring 3.1.1, however the current version 4.1.1 is showing the same behaviour.
My configuration looks like this (massivly simplified):
Interface: MyService:
public interface MyService {
public String getText();
}
MyService-Implementation for Portlet:
public class MyPortletService implements MyService {
#Override
public String getText() {
return this.getClass().toString();
}
}
MyService-Implementation for Servlet:
public class MyServletService implements MyService {
#Override
public String getText() {
return this.getClass().toString();
}
}
Bean to be used by Servlet and Portlet:
#Configurable
public class MyBean {
#Autowired
private MyService myService;
public String getText() {
return myService.getText();
}
}
Call in Portlet- and Servlet-Controller:
logger.trace("new MyBean().getText(): " + new MyBean().getText());
servlet-application-context.xml:
<bean class="my.app.PortletController" />
<bean class="my.app.MyServletService"/>
portet-application-context.xml:
<bean class="my.app.ServletController" />
<bean class="my.app.MyPortletService"/>
relevant dependencies in pom.xml
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.1.1.RELEASE</version>
</dependency> -->
compile-time-weaving configuration:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.6</version>
<configuration>
<complianceLevel>1.6</complianceLevel>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
Log output if calling servlet, portlet, servlet in that order:
new MyBean().getText(): class my.app.MyServletService
new MyBean().getText(): class my.app.MyPortletService
new MyBean().getText(): class my.app.MyPortletService
Update 2014-11-27:
I have now created a test-case outlining the problem:
https://github.com/ChrZae/servlet-portlet-spring-container-issue

Spring RESTful Service

I am unable to hit a Spring rest service I have created. I am new to spring and have been trying to follow the tutorials and find examples online. I am unable to determine what I am doing incorrectly.
Web.xml
<web-app>
<display-name>Friend List</display-name>
<servlet>
<servlet-name>friendlist</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>friendlist</servlet-name>
<url-pattern>/friend-list/*</url-pattern>
</servlet-mapping>
</web-app>
friend-list-servlet.xml
<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"
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">
<context:component-scan base-package="demo.model"/>
</beans>
HelloWorld.java
package demo.model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class HelloWorld {
public HelloWorld() {}
#RequestMapping("/hello")
public String hello() {
return "Hello, World!";
}
}
I am trying to return just the text, not a view, which is the reason I have used a #RestController. I am running Java JDK 7, Eclipse Luna, and Tomcat 7. I have tried hitting localhost:8080/friend-list/hello and get a 404. Also, I have inserted a #RequestMapping("/friend-list") above the header of the class and also received 404s going to both /friend-list/hello and /friend-list/friend-list/hello.
Tomcat Log:
INFO: Mapped URL path [/hello] onto handler 'helloWorld'
Jul 23, 2014 8:20:35 PM org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping registerHandler
INFO: Mapped URL path [/hello.*] onto handler 'helloWorld'
Jul 23, 2014 8:20:35 PM org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping registerHandler
INFO: Mapped URL path [/hello/] onto handler 'helloWorld'
POM.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>friend-list</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>friend-list Maven Webapp</name>
<url>http://maven.apache.org</url>
<build>
<finalName>friend-list</finalName>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.0.5</version>
<exclusions>
<exclusion>
<artifactId>jta</artifactId>
<groupId>javax.transaction</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
</dependencies>
</project>
Any assistance would be appreciated.
Couple of things:
*You need to update your web.xml: (hyphen is important with the servlet name)
<servlet>
<servlet-name>friend-list</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>friend-list</servlet-name>
<url-pattern>/friend-list/*</url-pattern>
</servlet-mapping>
*For Hello World you are missing a few things.
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
#Controller
#RequestMapping("/hello")
public class HelloWorld {
public HelloWorld() {
}
#RequestMapping(method = RequestMethod.GET)
#ResponseStatus(HttpStatus.OK)
#ResponseBody
public String hello() {
return "Hello, World!";
}
}
RequestMapping for the Resource then you are going to want to map the resource methods.
ResponseBody was missing as well
*Once your app is up and running you should be able to hit:
localhost:8080/myapp/friend-list/hello
Where myapp is whatever you named your app.
I like using postman ( Chrome plugin and easy to us.)
*http://spring.io/guides/tutorials/rest/2/ Excellent tutorial in regards to Spring and REST.
Spring wasn't loading your #RestController because the spring configuration file was not having a filename that matched the name of your servlet. So if your servlet name in Web.xml is friendlist, then your spring configuration file should be named friendlist-servlet.xml

Resources