I use Swagger 2 with non-spring-boot and I also can deploy my app on Tomcat and run it successfully. But the controller does not appear in swagger-ui.html, just the empty page with the green swagger title show up. I have spent two days on this issue. Would you give me some advice?
#Controller means the class as bellow:
#Api
#Controller
#RequestMapping("/user")
public class UserController {
protected Logger logger = LoggerFactory.getLogger(UserController.class);
#Autowired
private UserService userService;
#RequestMapping("/showInfos")
public #ResponseBody Object showUserInfos(){
logger.info("-----------------------showUserInfos-----------------------");
List<UserInfo> userInfos = userService.getUsers();
return userInfos;
}
my spring-mvc.xml configuration as follows:
<mvc:annotation-driven/>
<!#Controller inject bean -->
<context:component-scan base-package="com.roy.demo , version" />
<!-- Enables swgger ui -->
<mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/" />
<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/" />
<!-- Include a swagger configuration -->
<bean name="/applicationSwaggerConfig" class="com.roy.demo.config.ApplicationSwaggerConfig" />
also my swagger configuration class is as follows:
#EnableSwagger2
public class ApplicationSwaggerConfig {
private static final Logger LOGGER = Logger.getLogger(ApplicationSwaggerConfig.class);
#Bean
public Docket api() {
LOGGER.info("################################ into Docket api() #####################################");
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.roy.demo.controller"))
.paths(PathSelectors.any())
.build();
}
}
my maven pom.xml swagger2 dependency as follows:
<!-- Swagger 2.0 -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.5.0</version>
</dependency>
Bellow is the result when i enter the endpoint url:http://localhost:8080/Spring_SpringMVC_Mybatis/swagger-ui.html
I also new to Swagger but Below code I used for my swagger configuration and it works well for me.I done the configuration in class.
Configuration class.
#Configuration
#EnableWebMvc
#EnableSwagger2
#ComponentScan(basePackages = "com.*")
#PropertySource(value = { "classpath:log4j.properties" })
public class SpringConfig extends WebMvcConfigurerAdapter {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()).directModelSubstitute(LocalDate.class, String.class).genericModelSubstitutes(ResponseEntity.class)
.useDefaultResponseMessages(false)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
#SuppressWarnings("deprecation")
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo(
"API",
"API for xxxx",
"API TOS",
"Terms of service",
"xxx",
"License of API",
"");
return apiInfo;
}
}
Maven Dependency:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.4.0</version>
</dependency>
Controller Class
#RestController
#Api(value="users", description="Endpoint for user management")
public class Controller {
}
endpointurl:
https://localhost:8080/AppName/swagger-ui.html
clear your browser cache and try again.
or use incognito tab
It worked well for me
It happened to me that one of the controllers was not displayed. The problem was the kotlin class has not declared any package. Declaring a package in the controller fixed the problem.
Related
I am learning spring-security and created simple application to learn matchers. Unfortunately, I cannot get mvcMatchers to work. The other thing is that it works perfectly with antMatchers. Please see it's source below.
1) dependencies in pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
2) MvcWebApplicationInitializer:
public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SecurityConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { MvcWebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
3) MvcWebConfig
#Configuration
#EnableWebMvc
#ComponentScan("com.example.controller")
public class MvcWebConfig implements WebMvcConfigurer {
#Autowired
private ApplicationContext applicationContext;
#Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
}
}
4) SecurityConfig:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
#Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/secured/**").hasRole("ADMIN")
//.mvcMatchers(HttpMethod.GET, "/secured/**").hasRole("ADMIN")
.anyRequest().permitAll()
.and()
.formLogin();
}
}
5) SecurityWebInitializer:
public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer {}
6) MyController
#Controller
public class MyController {
#GetMapping("unsecured")
public String unsecured(Model model) {
model.addAttribute("message", "Unsecured");
return "index";
}
#GetMapping("secured/msg")
public String secured(Model model) {
model.addAttribute("message", "Secured");
return "index";
}
}
7) index.html is just simple Themeleaf template to output message
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
</head>
<body>
<p th:text="${message}"></p>
</body>
</html>
I package app as war, deploy it to Tomcat 9 application server, and open warname/unsecured and warname/secured/msg URLs and it works as expected (unsecured just outputs message 'unsecured', secured asks for login/password. After logging in it displays page with message 'secured'). When I comment antMatchers and uncomment mvcMatchers in SecurityConfig navigating to any of these 2 urls gives me standard 404 Tomcat page. I tried to provide mvcMatchers with different patterns, such as: /secured/msg, /secured/msg/, secured/msg, /secured/msg/*, and every time I got 404. While remote debugging of app I have found that it seems that mvcMatcher.match is not get called, while antMatcher.match is called during attemt to access warname/secured/msg page. Can you please tell me how I can make app to work with mvcMatchers the same way as it works now with antMatchers?
Try add annotation #PreAuthorized("hasRole('ADMIN')") abow your endpoints like this:
#PreAuthorized("hasRole('ADMIN')")
#GetMapping("secured/msg")
public String secured(Model model) {
model.addAttribute("message", "Secured");
return "index";
}
btw. You should use direct paths in mvcMatchers like:
mvcMatchers(HttpMeethod.GET, "/secured/msg"...)
Have a codebase which uses SpringMVC 4.0.3.RELEASE for Restful Web Services.
Codebase contains a fully functional Restful Web Service which I can verify works using postman and curl.
However, when trying to write a unit test for the particular Restful Web Service using MockMvc, I become blocked with trying to obtain the JSON content from the unit test.
Am wondering if its a config issue or an issue where I am not creating a fake object correctly (since this doesn't rely on tomcat and is standalone).
pom.xml:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.0.3.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- A bunch of other Spring libs omitted from this post -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
<version>0.9.1</version>
<scope>test</scope>
</dependency>
WebConfig:
package com.myapp.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#EnableWebMvc
#Configuration
#ComponentScan("com.myapp.rest")
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
}
ServletInitializer:
package com.myapp.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.myapp.config.WebConfig;
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
}
UserController:
#RestController
#RequestMapping("/v2")
public class UserController {
private final UserDAO dao;
private HttpHeaders headers = null;
#Autowired
public UserController(UserDAO dao) {
this.dao = dao;
headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
}
#RequestMapping(value = "users/{appId}", method = RequestMethod.GET, produces="application/json")
#ResponseBody
public ResponseEntity<Object> getUserDetails(#PathVariable String appId) {
Object jsonPayload = dao.getUser(appId);
return new ResponseEntity<Object>(jsonPayload, headers, HttpStatus.OK);
}
}
UserDAO:
#Repository
public class UserDAO {
private JdbcTemplate jdbcTemplate;
#Autowired
public UserDAO(#Qualifier("dataSourceDB") DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// Finders methods (such as the getUser(appId)) which use Spring JDBC
}
WEB-INF/web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>MyApp</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
</web-app>
WEB-INF/mvc-dispatcher-servlet.xml:
<beans xmlns="http://www.springframework.org/schema/beans">
<import resource="classpath:database.xml" />
<context:component-scan base-package="com.myapp.rest" />
<mvc:annotation-driven />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
src/main/resources/database.xml:
<beans xmlns="http://www.springframework.org/schema/beans">
<bean id="dataSourceDB" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>${jdbc.driver}</value></property>
<property name="url"><value>${db.url}</value></property>
<property name="username"><value>${db.username}</value></property>
<property name="password"><value>${db.password}</value></property>
</bean>
</beans>
My actual unit test:
package com.myapp.rest.controllers;
RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:**/mvc-dispatcher-servlet.xml")
#WebAppConfiguration
public class UserControllerTest {
private MockMvc mockMvc;
#Mock
private UserDAO dao;
#InjectMocks
private UserController controller;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Test
public void getUserDetails() throws Exception {
String appId = "23bdr4560l";
mockMvc.perform(get("/v2/users/{appId}",appId)
.accept(MediaType.APPLICATION_JSON))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(print());
}
}
When I invoke my build locally:
mvn clean install
Generated output to stdout:
Running com.myapp.rest.controllers.UserControllerTest
MockHttpServletRequest:
HTTP Method = GET
Request URI = /v2/users/23bdr4560l
Parameters = {}
Headers = {Accept=[application/json]}
Handler:
Type = com.myapp.rest.controllers.UserController
Method = public org.springframework.http.ResponseEntity<java.lang.Object> com.myapp.rest.controllers.UserController.getUserDetails(java.lang.String)
Async:
Was async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/json]}
Content type = application/json
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.728 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Notice how the JSON body part is empty / null:
Body =
So, when trying to access the JSON payload using jsonPath:
#Test
public void getUserDetails() throws Exception {
String appId = "23bdr4560l";
mockMvc.perform(get("/v2/users/{appId}",appId)
.accept(MediaType.APPLICATION_JSON))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(2)))
.andDo(print());
}
Received the following error:
Results :
Tests in error:
getUserDetails(com.myapp.rest.controllers.UserControllerTest): json can not be null or empty
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
What am I possbily doing wrong?
Obviously, I need to mock out the response but have Googled this and others using MockMvc were able to obtain a JSON their test.
Is this a config issue (do I need to put some type of annotation for my unit test)?
Do, I need to instantiate the controller inside my test?
What weird is that the actual Rest Call works (returns a valid JSON) using postman and curl...
This codebase does not have an #Service class / layer, its just #RestController speaking to #Repository (see above).
Really thought that testing support for Spring MVC based Restful Web Services would be a lot easier.
Am running out of ideas...
Any help would me most appreciated...
When you are trying to mock the bean like this, it tries to create the mock with the default constructor.
#Mock
private UserDAO dao
It works in case of actual rest call because you provide the dependent DataSource dataSource at runtime. Providing a valid dependent mock for the UserDAO class works.
Since you are mocking the UserDAO you need to provide some mock expectations for the call:
Object jsonPayload = dao.getUser(appId);
Inside your Controller or it will return null by default. To do this use the Mockito.when() method inside your test prior to the MockMvc call:
when(dao.getUser(anyString())).thenReturn(json)
where json is some hard coded json Object you set up yourself.
For starters, since you're using MockMvcBuilders.standaloneSetup(...) you are in fact not using the Spring TestContext Framework (TCF) to load your WebApplicationContext. So just completely delete the following declarations in your test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:**/mvc-dispatcher-servlet.xml")
#WebAppConfiguration
Also, you can completely ignore your XML configuration files since they are not used without a WebApplicationContext.
As an aside, web.xml and Servlet initializers are never used by the TCF, so you can ignore them as well.
Then, as mentioned by #Plog, you'll need to set up the expectations for your mocked UserDAO; otherwise, the invocation of dao.getUser(appId) always returns null which results in an empty response body.
Regards,
Sam (author of the Spring TestContext Framework)
Validation of RequestParam using custom validation annotation #ValidCode doesn't work. But If use #Pattern instead it starts working. What am I doing wrong, please?
The controller:
#Validated
#RestController
public class MyEndpoint {
#RequestMapping(path = "/test", method = GET)
public MyResponse findItems(#ValidCode #RequestParam("code") String code) {
return new MyResponse("A001");
}
}
My validation annotation:
#Retention(RUNTIME)
#Target({FIELD, PARAMETER})
#Pattern(regexp = "^[A-Z0-9]{4}?$")
public #interface ValidCode {
String message() default "{ValidCode.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Web MVC config:
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Bean
public Validator validator() {
return new LocalValidatorFactoryBean();
}
#Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
}
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 http://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>1.3.1.RELEASE</version>
<relativePath></relativePath>
</parent>
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
...
</dependencies>
</project>
BUT if I change controller method following way validation starts working:
#RequestMapping(path = "/test", method = GET)
public MyResponse findItems(#Pattern(regexp="^[A-Z0-9]{2}?$") #RequestParam("code") String code) {
return new MyResponse("A001");
}
Many thanks in advance.
The problem is the that tiles configuration is not getting applied
everytime.
I have integrated Apache tiles 3 with spring MVC. I have used annotation based configuration of spring. The problem in the application is that the tiles definitions get applied on random basis. When I try to run the application, the tiles configuration that we have configured may or may not get applied.
I am using Apache tomcat 7. Is this problem related with server? Is this problem related with Configuration? Or If Any.
Here is my Code
MVC Configuration
Annotation base Java Configuration using Spring
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = { "com.om.*" })
public class MVCConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/layout/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public TilesViewResolver getTilesViewResolver() {
TilesViewResolver tilesViewResolver = new TilesViewResolver();
tilesViewResolver.setViewClass(TilesView.class);
return tilesViewResolver;
}
#Bean
public TilesConfigurer getTilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
tilesConfigurer.setCheckRefresh(true);
tilesConfigurer.setDefinitionsFactoryClass(TilesDefinitionsConfig.class);
// Add apache tiles definitions
TilesDefinitionsConfig.addDefinitions();
return tilesConfigurer;
}
}
MVCInitializer
public class MVCInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { MVCConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
TilesDefinitionsConfig
public final class TilesDefinitionsConfig implements DefinitionsFactory {
private static final Map<String, Definition> tilesDefinitions = new HashMap<String,Definition>();
private static final Attribute BASE_TEMPLATE = new Attribute("/WEB-INF/views/layout/defaultLayout.jsp");
public Definition getDefinition(String name, Request tilesContext) {
System.out.println("3");
return tilesDefinitions.get(name);
}
/**
* #param name <code>Name of the view</code>
* #param title <code>Page title</code>
* #param body <code>Body JSP file path</code>
*
* <code>Adds default layout definitions</code>
*/
private static void addDefaultLayoutDef(String name, String title, String body) {
Map<String, Attribute> attributes = new HashMap<String,Attribute>();
attributes.put("title", new Attribute(title));
attributes.put("header", new Attribute("/WEB-INF/views/layout/header.jsp"));
attributes.put("menu", new Attribute("/WEB-INF/views/layout/menu.jsp"));
attributes.put("body", new Attribute(body));
attributes.put("footer", new Attribute("/WEB-INF/views/layout/footer.jsp"));
tilesDefinitions.put(name, new Definition(name, BASE_TEMPLATE, attributes));
}
/**
* <code>Add Apache tiles definitions</code>
*/
public static void addDefinitions(){
addDefaultLayoutDef("welcome", "welcome", "/WEB-INF/views/layout/welcome.jsp");
addDefaultLayoutDef("personList", "viewPerson", "/WEB-INF/views/layout/personList.jsp");
}
}
Controller
#Controller
public class SpringTilesController {
#RequestMapping(value="welcome")
public ModelAndView index() {
ModelAndView model=new ModelAndView();
System.out.println("In Controller");
model.setViewName("welcome");
return model;
}
#RequestMapping(value="viewPerson")
public ModelAndView viewPersons(Model model) {
Map<String, List<Person>> persons =
new HashMap<String, List<Person>>();
persons.put("persons", Person.createPersons());
return new ModelAndView("personList", persons);
}
}
Entity
public class Person {
private String name, email;
private int age;
public Person(String name, String email, int age) {
this.name = name;
this.email = email;
this.age = age;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public String getEmail() {return email;}
public void setEmail(String email) {this.email = email;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
#Override
public String toString()
{
return String.format(
"Person [name = %s, email = %s, age = %d]",
name, email, age);
}
public static List<Person> createPersons() {
List<Person> persons = new ArrayList<Person>();
persons.add(new Person("Tousif", "tousif#mail.com", 32));
persons.add(new Person("Asif", "asif#mail.com", 28));
persons.add(new Person("Ramiz", "ramiz#mail.com", 26));
persons.add(new Person("Rizwan", "rizwan#mail.com", 32));
persons.add(new Person("Amol", "amol#mail.com", 33));
persons.add(new Person("Ramdas", "ramdas#mail.com", 31));
return persons;
}
}
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>com.om</groupId>
<artifactId>TilesDemo</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>TilesDemo Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<jdk.version>1.7</jdk.version>
<spring.version>4.1.6.RELEASE</spring.version>
<spring.security.version>4.0.1.RELEASE</spring.security.version>
<jstl.version>1.2</jstl.version>
<javax.servlet.version>3.1.0</javax.servlet.version>
<mysql.connector.version>5.1.31</mysql.connector.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- jstl for jsp page -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!-- Apache Tiles -->
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-api</artifactId>
<version>3.0.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-core</artifactId>
<version>3.0.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>3.0.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-servlet</artifactId>
<version>3.0.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-template</artifactId>
<version>3.0.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-el</artifactId>
<version>3.0.5</version>
<scope>compile</scope>
</dependency>
<!-- Spring 4 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<build>
<finalName>TilesDemo</finalName>
</build>
</project>
Keep The header,footer,menu as per the requirements.
This is defaultLayout.jsp page
<%# taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<title><tiles:insertAttribute name="title" ignore="true"></tiles:insertAttribute></title>
</head>
<body style="background-color: #FFF">
<div class="page">
<tiles:insertAttribute name="header" />
<div class="content">
<div id="body">
<tiles:insertAttribute name="body" />
</div>
</div>
<tiles:insertAttribute name="footer" />
</div>
</body>
</html>
footer.jsp
<hr />
<div class="span-1 prepend-3"> </div>
<div class="span-16 last">
<p>
<b> Technology</b>
( All rights Reserved)
</p>
</div>
header.jsp
<div class="span-24">
<img src="resources/images/images.png"
width="950" style="padding-top:10px;" />
</div>
menu.jsp
Left side menu bar options
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<ul style="list-style:none;line-height:28px;">
<li><spring:url value="/index" var="homeUrl" htmlEscape="true" />
Home
</li>
<li><spring:url value="/viewPerson" var="personListUrl" htmlEscape="true" />
Person List
</li>
</ul>
welcome.jsp
This is the body Page on which header, footer and menu will be applied.
<div style="margin:10px;">
<h3>SpringMVC - Tiles3 Integration tutorial</h3>
<p>By:- XYZ</p>
</div>
The problem is the that tiles configuration is not getting applied everytime.
As you can see in this project Tiles configuration without xml the developer had a similar problem, the tiles configuration isn't working.
He found that if you call the view with the same name of the file.jsp, somethings going bad.
public static void addDefinitions(){
addDefaultLayoutDef("welcome", "welcome", "/WEB-INF/views/layout/welcome.jsp");
addDefaultLayoutDef("personList", "viewPerson", "/WEB-INF/views/layout/personList.jsp");
}
Try to use different name for the view and the file.jsp.
Try with
addDefaultLayoutDef("welcome", "Welcome", "/WEB-INF/views/layout/welcome.jsp");
Should work if the rest of the code is correct.
Maybe you need to define the view resolver's order precedence, something like this:
#Bean
public InternalResourceViewResolver internalResourceViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(JstlView.class);
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
//resolver.setOrder(2);
return resolver;
}
//configuracion de apache tiles
#Bean
public TilesViewResolver getTilesViewResolver() {
TilesViewResolver tilesViewResolver = new TilesViewResolver();
tilesViewResolver.setViewClass(TilesView.class);
// tiles view resolver va ha ser el primero en mostrarse
tilesViewResolver.setOrder(1);
return tilesViewResolver;
}
i am new to Spring MVC, i have created spring 3.2 project using maven in eclipse. i am implementing AbstractAnnotationConfigDispatcherServletInitializer class for java based configuration.
i have following plugins and dependencies in pom.xml
<build>
<plugins>
<!--source level should be 1.6 (which is not Maven default) for java EE
6 projects, so let's change it -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<!-- When using xml-less approach, you need to disable Maven's warning
about missing web.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!--We need servlet API for compiling the classes. Not needed in runtime
-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--adding spring mvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<!-- Add Taglib support -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
Initializer class is as......
public class Initializer extends AbstractAnnotationConfigDispatcherServletInitializer{
#Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebappConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
WebappConfig class is as......
#Configuration
#ComponentScan(basePackages={"com.sandip.controllers"})
#EnableWebMvc
public class WebappConfig extends WebMvcConfigurerAdapter{
//add view Resolver, Tell SpingMVC where to find view scripts
#Bean
public InternalResourceViewResolver setupViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
and finally i have a HomeController as..........
#Controller
public class HomeContoller {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home() {
return "home";
}
}
when i run this my project with jetty after maven build it display the following output in browser.....
springZeroXml is my project name there is no errro in console, please help ..........
I did lot of googleing and find out i need to override the addViewControllers method of WebMvcConfigurerAdapter class in WebAppConfig. and code is..........
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}