Merge branch 'master' into JAVA-3533
This commit is contained in:
@@ -20,8 +20,12 @@
|
||||
<module>spring-mvc-basics-4</module>
|
||||
<module>spring-mvc-crash</module>
|
||||
<module>spring-mvc-forms-jsp</module>
|
||||
<module>spring-mvc-views</module>
|
||||
<module>spring-mvc-webflow</module>
|
||||
<module>spring-rest-angular</module>
|
||||
<module>spring-rest-http</module>
|
||||
<module>spring-rest-http-2</module>
|
||||
<module>spring-resttemplate-2</module>
|
||||
<module>spring-thymeleaf</module>
|
||||
<module>spring-thymeleaf-2</module>
|
||||
<module>spring-thymeleaf-3</module>
|
||||
|
||||
@@ -78,12 +78,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-context</artifactId>
|
||||
<version>${springcloud.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
@@ -149,7 +143,6 @@
|
||||
<jpa.version>2.2</jpa.version>
|
||||
<guava.version>18.0</guava.version>
|
||||
<subethasmtp.version>3.1.7</subethasmtp.version>
|
||||
<springcloud.version>2.0.2.RELEASE</springcloud.version>
|
||||
<httpclient.version>4.5.8</httpclient.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -5,3 +5,6 @@ spring.mvc.pathmatch.use-suffix-pattern=true
|
||||
#spring.mvc.contentnegotiation.favor-path-extension=true
|
||||
#spring.mvc.contentnegotiation.favor-parameter=true
|
||||
#spring.mvc.contentnegotiation.parameter-name=mediaType
|
||||
|
||||
# https://github.com/spring-projects/spring-boot/issues/24207
|
||||
spring.main.allow-bean-definition-overriding=true
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
### Relevant Articles:
|
||||
|
||||
- [Spring MVC Themes](https://www.baeldung.com/spring-mvc-themes)
|
||||
- [Apache Tiles Integration with Spring MVC](https://www.baeldung.com/spring-mvc-apache-tiles)
|
||||
@@ -0,0 +1,127 @@
|
||||
<?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>
|
||||
<artifactId>spring-mvc-views</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>spring-mvc-views</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-spring-5</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>parent-spring-5/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet.jsp</groupId>
|
||||
<artifactId>javax.servlet.jsp-api</artifactId>
|
||||
<version>${javax.servlet.jsp-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>${jstl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>${spring.data.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>${hsqldb.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${spring.security.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>${spring.security.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-taglibs</artifactId>
|
||||
<version>${spring.security.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tiles</groupId>
|
||||
<artifactId>tiles-jsp</artifactId>
|
||||
<version>${apache-tiles.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>spring-mvc-views</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.0.2</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<warSourceDirectory>src/main/webapp</warSourceDirectory>
|
||||
<warName>spring-mvc-views</warName>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<outputDirectory>${deploy-path}</outputDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<javax.servlet.jsp-api.version>2.3.3</javax.servlet.jsp-api.version>
|
||||
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
|
||||
<spring.version>5.2.1.RELEASE</spring.version>
|
||||
<spring.security.version>5.2.1.RELEASE</spring.security.version>
|
||||
<spring.data.version>2.2.2.RELEASE</spring.data.version>
|
||||
<cglib.version>2.2.2</cglib.version>
|
||||
<hsqldb.version>2.5.0</hsqldb.version>
|
||||
<hibernate.version>5.4.9.Final</hibernate.version>
|
||||
<deploy-path>enter-location-of-server</deploy-path>
|
||||
<apache-tiles.version>3.0.8</apache-tiles.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.baeldung.themes.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@EnableJpaRepositories(basePackages = "com.baeldung")
|
||||
public class DataSourceConfig {
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
||||
return builder.setType(EmbeddedDatabaseType.HSQL)
|
||||
.addScripts("db/sql/create-db.sql", "db/sql/insert-data.sql")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
|
||||
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||
em.setDataSource(dataSource);
|
||||
em.setPackagesToScan("com.baeldung.themes.domain");
|
||||
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
|
||||
return em;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
|
||||
return new JpaTransactionManager(emf);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
|
||||
return new PersistenceExceptionTranslationPostProcessor();
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package com.baeldung.themes.config;
|
||||
|
||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||
|
||||
public class InitSecurity extends AbstractSecurityWebApplicationInitializer {
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.themes.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.jdbcAuthentication()
|
||||
.passwordEncoder(passwordEncoder())
|
||||
.dataSource(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
http.csrf()
|
||||
.disable()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/anonymous*").anonymous()
|
||||
.antMatchers("/login*").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin()
|
||||
.and()
|
||||
.logout()
|
||||
.logoutUrl("/logout.do")
|
||||
.invalidateHttpSession(true)
|
||||
.clearAuthentication(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/themes/**");
|
||||
}
|
||||
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.baeldung.themes.config;
|
||||
|
||||
import com.baeldung.themes.resolver.UserPreferenceThemeResolver;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.ui.context.support.ResourceBundleThemeSource;
|
||||
import org.springframework.web.servlet.ThemeResolver;
|
||||
import org.springframework.web.servlet.config.annotation.*;
|
||||
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackages="com.baeldung")
|
||||
@EnableWebMvc
|
||||
public class ThemeMVCConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/themes/**").addResourceLocations("classpath:/themes/");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(themeChangeInterceptor());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ThemeChangeInterceptor themeChangeInterceptor() {
|
||||
ThemeChangeInterceptor interceptor = new ThemeChangeInterceptor();
|
||||
interceptor.setParamName("theme");
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ResourceBundleThemeSource resourceBundleThemeSource() {
|
||||
ResourceBundleThemeSource themeSource = new ResourceBundleThemeSource();
|
||||
themeSource.setFallbackToSystemLocale(true);
|
||||
return themeSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ThemeResolver themeResolver() {
|
||||
UserPreferenceThemeResolver themeResolver = new UserPreferenceThemeResolver();
|
||||
themeResolver.setDefaultThemeName("light");
|
||||
return themeResolver;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void configureViewResolvers(ViewResolverRegistry resolverRegistry) {
|
||||
resolverRegistry.jsp();
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.baeldung.themes.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.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
|
||||
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ComponentScan(basePackages = "com.baeldung.themes")
|
||||
public class TilesApplicationConfiguration implements WebMvcConfigurer {
|
||||
|
||||
/**
|
||||
* Configure TilesConfigurer.
|
||||
*/
|
||||
@Bean
|
||||
public TilesConfigurer tilesConfigurer() {
|
||||
TilesConfigurer tilesConfigurer = new TilesConfigurer();
|
||||
tilesConfigurer.setDefinitions(new String[] { "/WEB-INF/views/**/tiles.xml" });
|
||||
tilesConfigurer.setCheckRefresh(true);
|
||||
return tilesConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure ViewResolvers to deliver views.
|
||||
*/
|
||||
@Override
|
||||
public void configureViewResolvers(ViewResolverRegistry registry) {
|
||||
TilesViewResolver viewResolver = new TilesViewResolver();
|
||||
registry.viewResolver(viewResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure ResourceHandlers to serve static resources
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.themes.config;
|
||||
|
||||
import org.springframework.web.WebApplicationInitializer;
|
||||
import org.springframework.web.context.ContextLoaderListener;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRegistration;
|
||||
|
||||
public class WebInitializer implements WebApplicationInitializer {
|
||||
@Override
|
||||
public void onStartup(javax.servlet.ServletContext servletContext) throws ServletException {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.register(DataSourceConfig.class);
|
||||
context.register(ThemeMVCConfig.class);
|
||||
//context.register(TilesApplicationConfiguration.class);
|
||||
|
||||
|
||||
servletContext.addListener(new ContextLoaderListener(context));
|
||||
servletContext.setInitParameter("spring.profiles.active", "database");
|
||||
|
||||
ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
|
||||
|
||||
servlet.setLoadOnStartup(1);
|
||||
servlet.addMapping("/");
|
||||
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.themes.controllers;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class AppController {
|
||||
|
||||
@RequestMapping("/")
|
||||
public String home() {
|
||||
return "index";
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.themes.controllers;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/")
|
||||
public class TilesController {
|
||||
|
||||
@RequestMapping(value = { "/" }, method = RequestMethod.GET)
|
||||
public String homePage(ModelMap model) {
|
||||
return "home";
|
||||
}
|
||||
|
||||
@RequestMapping(value = { "/apachetiles" }, method = RequestMethod.GET)
|
||||
public String productsPage(ModelMap model) {
|
||||
return "apachetiles";
|
||||
}
|
||||
|
||||
@RequestMapping(value = { "/springmvc" }, method = RequestMethod.GET)
|
||||
public String contactUsPage(ModelMap model) {
|
||||
return "springmvc";
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.themes.domain;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "preferences")
|
||||
public class UserPreference {
|
||||
@Id
|
||||
private String username;
|
||||
|
||||
private String theme;
|
||||
|
||||
public String getTheme() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
public void setTheme(String theme) {
|
||||
this.theme = theme;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.baeldung.themes.repository;
|
||||
|
||||
import com.baeldung.themes.domain.UserPreference;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
public interface UserPreferenceRepository extends PagingAndSortingRepository<UserPreference, String> {
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.baeldung.themes.resolver;
|
||||
|
||||
import com.baeldung.themes.domain.UserPreference;
|
||||
import com.baeldung.themes.repository.UserPreferenceRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.ThemeResolver;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Optional;
|
||||
|
||||
public class UserPreferenceThemeResolver implements ThemeResolver {
|
||||
|
||||
public static final String THEME_REQUEST_ATTRIBUTE_NAME = UserPreferenceThemeResolver.class.getName() + ".THEME";
|
||||
|
||||
@Autowired(required = false)
|
||||
Authentication authentication;
|
||||
|
||||
@Autowired
|
||||
UserPreferenceRepository userPreferenceRepository;
|
||||
|
||||
private String defaultThemeName;
|
||||
|
||||
public String getDefaultThemeName() {
|
||||
return defaultThemeName;
|
||||
}
|
||||
|
||||
public void setDefaultThemeName(String defaultThemeName) {
|
||||
this.defaultThemeName = defaultThemeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveThemeName(HttpServletRequest request) {
|
||||
String themeName = findThemeFromRequest(request).orElse(findUserPreferredTheme().orElse(getDefaultThemeName()));
|
||||
request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);
|
||||
return themeName;
|
||||
}
|
||||
|
||||
private Optional<String> findUserPreferredTheme() {
|
||||
Authentication authentication = SecurityContextHolder.getContext()
|
||||
.getAuthentication();
|
||||
UserPreference userPreference = getUserPreference(authentication).orElse(new UserPreference());
|
||||
return Optional.ofNullable(userPreference.getTheme());
|
||||
}
|
||||
|
||||
private Optional<String> findThemeFromRequest(HttpServletRequest request) {
|
||||
return Optional.ofNullable((String) request.getAttribute(THEME_REQUEST_ATTRIBUTE_NAME));
|
||||
}
|
||||
|
||||
private Optional<UserPreference> getUserPreference(Authentication authentication) {
|
||||
return isAuthenticated(authentication) ? userPreferenceRepository.findById(((User) authentication.getPrincipal()).getUsername()) : Optional.empty();
|
||||
}
|
||||
|
||||
private boolean isAuthenticated(Authentication authentication) {
|
||||
return authentication != null && authentication.isAuthenticated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThemeName(HttpServletRequest request, HttpServletResponse response, String theme) {
|
||||
Authentication authentication = SecurityContextHolder.getContext()
|
||||
.getAuthentication();
|
||||
if (isAuthenticated(authentication)) {
|
||||
request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, theme);
|
||||
UserPreference userPreference = getUserPreference(authentication).orElse(new UserPreference());
|
||||
userPreference.setUsername(((User) authentication.getPrincipal()).getUsername());
|
||||
userPreference.setTheme(StringUtils.hasText(theme) ? theme : null);
|
||||
userPreferenceRepository.save(userPreference);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
styleSheet=themes/black.css
|
||||
background=black
|
||||
@@ -0,0 +1,2 @@
|
||||
styleSheet=themes/black.css
|
||||
background=black
|
||||
@@ -0,0 +1,17 @@
|
||||
create table users (
|
||||
username varchar(50) not null primary key,
|
||||
password varchar(256) not null,
|
||||
enabled boolean not null
|
||||
);
|
||||
|
||||
|
||||
create table authorities (
|
||||
username varchar(50) not null,
|
||||
authority varchar(50) not null
|
||||
);
|
||||
|
||||
|
||||
create table preferences (
|
||||
username varchar(50) not null,
|
||||
theme varchar(50)
|
||||
);
|
||||
@@ -0,0 +1,6 @@
|
||||
insert into users values('john', '$2a$10$cjcbIX/aLe12PpGZ.vQfweLiB7K1QTC5enTk3oD0deCMdtj2Sx.im', 1);
|
||||
insert into users values('admin', '$2a$10$cjcbIX/aLe12PpGZ.vQfweLiB7K1QTC5enTk3oD0deCMdtj2Sx.im', 1);
|
||||
|
||||
insert into authorities values('john', 'USER');
|
||||
insert into authorities values('admin', 'USER');
|
||||
insert into authorities values('admin', 'ADMIN');
|
||||
@@ -0,0 +1,2 @@
|
||||
styleSheet=themes/white.css
|
||||
background=black
|
||||
@@ -0,0 +1,2 @@
|
||||
styleSheet=themes/white.css
|
||||
background=black
|
||||
@@ -0,0 +1,8 @@
|
||||
body {
|
||||
justify-content : center;
|
||||
background-color : black;
|
||||
color : white;
|
||||
text-align : center;
|
||||
margin-left : 15%;
|
||||
margin-right : 15%;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
body {
|
||||
justify-content : center;
|
||||
background-color : white;
|
||||
color : black;
|
||||
text-align : center;
|
||||
margin-left : 15%;
|
||||
margin-right : 15%;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
|
||||
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
||||
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" href="<spring:theme code='styleSheet'/>"/>
|
||||
<title>Themed Application</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Themed Application</h1>
|
||||
<hr />
|
||||
</header>
|
||||
<section>
|
||||
<h2>Spring MVC Theme Demo</h2>
|
||||
<security:authorize access="isAuthenticated()">
|
||||
<h4>User : <security:authentication property="principal.username" /></h4>
|
||||
</security:authorize>
|
||||
<form action="<c:url value='/'/>" method="POST" name="themeChangeForm" id="themeChangeForm">
|
||||
<div>
|
||||
<h4>
|
||||
Change Theme
|
||||
</h4>
|
||||
</div>
|
||||
<select id="theme" name="theme" onChange="submitForm()">
|
||||
<option value="">Reset</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<form action="<c:url value='/logout.do'/>" method="POST" name="logoutForm">
|
||||
<button type="submit" name="submit">Sign Out</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function submitForm() {
|
||||
document.themeChangeForm.submit();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||
pageEncoding="ISO-8859-1"%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Apache Tiles</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Tiles with Spring MVC Demo</h2>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||
pageEncoding="ISO-8859-1"%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Home</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Welcome to Apache Tiles integration with Spring MVC</h2>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||
pageEncoding="ISO-8859-1"%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Spring MVC</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Spring MVC configured to work with Apache Tiles</h2>
|
||||
</body>
|
||||
</html>
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||
pageEncoding="ISO-8859-1"%>
|
||||
<%@ page isELIgnored="false"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title><tiles:getAsString name="title" /></title>
|
||||
<link href="<c:url value='/static/css/app.css' />" rel="stylesheet"></link>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="flex-container">
|
||||
<tiles:insertAttribute name="header" />
|
||||
<tiles:insertAttribute name="menu" />
|
||||
<article class="article">
|
||||
<tiles:insertAttribute name="body" />
|
||||
</article>
|
||||
<tiles:insertAttribute name="footer" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
|
||||
<footer>copyright © Baeldung</footer>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<header>
|
||||
<h1>Welcome to Spring MVC integration with Apache Tiles</h1>
|
||||
</header>
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<nav class="nav">
|
||||
<a href="${pageContext.request.contextPath}/"></a>
|
||||
<ul id="menu">
|
||||
<li><a href="${pageContext.request.contextPath}/">Home</a></li>
|
||||
<li><a href="${pageContext.request.contextPath}/springmvc">SpringMVC</a></li>
|
||||
<li><a href="${pageContext.request.contextPath}/apachetiles">ApacheTiles</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
|
||||
|
||||
<tiles-definitions>
|
||||
|
||||
<!-- Template Definition -->
|
||||
<definition name="template-def"
|
||||
template="/WEB-INF/views/tiles/layouts/defaultLayout.jsp">
|
||||
<put-attribute name="title" value="" />
|
||||
<put-attribute name="header" value="/WEB-INF/views/tiles/templates/defaultHeader.jsp" />
|
||||
<put-attribute name="menu" value="/WEB-INF/views/tiles/templates/defaultMenu.jsp" />
|
||||
<put-attribute name="body" value="" />
|
||||
<put-attribute name="footer" value="/WEB-INF/views/tiles/templates/defaultFooter.jsp" />
|
||||
</definition>
|
||||
|
||||
<!-- Main Page -->
|
||||
<definition name="home" extends="template-def">
|
||||
<put-attribute name="title" value="Welcome" />
|
||||
<put-attribute name="body" value="/WEB-INF/views/pages/home.jsp" />
|
||||
</definition>
|
||||
|
||||
<!-- Apache Tiles Page -->
|
||||
<definition name="apachetiles" extends="template-def">
|
||||
<put-attribute name="title" value="ApacheTiles" />
|
||||
<put-attribute name="body" value="/WEB-INF/views/pages/apachetiles.jsp" />
|
||||
</definition>
|
||||
|
||||
<!-- Spring MVC Page -->
|
||||
<definition name="springmvc" extends="template-def">
|
||||
<put-attribute name="title" value="SpringMVC" />
|
||||
<put-attribute name="body" value="/WEB-INF/views/pages/springmvc.jsp" />
|
||||
</definition>
|
||||
|
||||
</tiles-definitions>
|
||||
@@ -0,0 +1,36 @@
|
||||
.flex-container {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-flow: row wrap;
|
||||
flex-flow: row wrap;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.flex-container > * {
|
||||
padding: 15px;
|
||||
-webkit-flex: 1 100%;
|
||||
flex: 1 100%;
|
||||
}
|
||||
|
||||
.article {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
header {background: black;color:white;}
|
||||
footer {background: #aaa;color:white;}
|
||||
.nav {background:#eee;}
|
||||
|
||||
.nav ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav ul a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media all and (min-width: 768px) {
|
||||
.nav {text-align:left;-webkit-flex: 1 auto;flex:1 auto;-webkit-order:1;order:1;}
|
||||
.article {-webkit-flex:5 0px;flex:5 0px;-webkit-order:2;order:2;}
|
||||
footer {-webkit-order:3;order:3;}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
## Spring MVC WebFlow
|
||||
|
||||
This module contains articles about Spring MVC Web Flow
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [Guide to Spring Web Flow](https://www.baeldung.com/spring-web-flow)
|
||||
@@ -0,0 +1,120 @@
|
||||
<?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>
|
||||
<artifactId>spring-mvc-webflow</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>spring-mvc-webflow</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Web Flow -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.webflow</groupId>
|
||||
<artifactId>spring-webflow</artifactId>
|
||||
<version>${spring.webflow}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- web -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>${jstl.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency> <!-- needed to bridge to slf4j for projects that use the log4j APIs directly -->
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<version>${spring-boot-starter-test.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>spring-mvc-webflow</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.tomee.maven</groupId>
|
||||
<artifactId>tomee-maven-plugin</artifactId>
|
||||
<version>8.0.1</version>
|
||||
<configuration>
|
||||
<tomeeHttpPort>8080</tomeeHttpPort>
|
||||
<context>spring-mvc-webflow</context>
|
||||
<reloadOnUpdate>true</reloadOnUpdate>
|
||||
<tomeeClassifier>plume</tomeeClassifier>
|
||||
<synchronization>
|
||||
<extensions>
|
||||
<extension>.class</extension>
|
||||
</extensions>
|
||||
</synchronization>
|
||||
<args>-Xmx2048m -XX:PermSize=256m -Dtomee.serialization.class.blacklist=- -Dtomee.serialization.class.whitelist=*</args>
|
||||
<removeDefaultWebapps>true</removeDefaultWebapps>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<!-- Spring -->
|
||||
<org.springframework.version>5.0.1.RELEASE</org.springframework.version>
|
||||
|
||||
<!-- Spring Web Flow -->
|
||||
<spring.webflow>2.5.0.RELEASE</spring.webflow>
|
||||
|
||||
<httpcore.version>4.4.5</httpcore.version>
|
||||
<httpclient.version>4.5.2</httpclient.version>
|
||||
|
||||
<!-- Maven plugins -->
|
||||
<maven-resources-plugin.version>2.7</maven-resources-plugin.version>
|
||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||
<spring-boot-starter-test.version>1.5.10.RELEASE</spring-boot-starter-test.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.baeldung.servlet;
|
||||
|
||||
import javax.servlet.ServletRegistration.Dynamic;
|
||||
|
||||
import com.baeldung.spring.WebFlowConfig;
|
||||
import com.baeldung.spring.WebMvcConfig;
|
||||
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
|
||||
|
||||
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
|
||||
|
||||
public WebInitializer() {
|
||||
super();
|
||||
}
|
||||
|
||||
// API
|
||||
protected Class<?>[] getRootConfigClasses() {
|
||||
return new Class<?>[] { WebMvcConfig.class, WebFlowConfig.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getServletConfigClasses() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getServletMappings() {
|
||||
return new String[] { "/" };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customizeRegistration(final Dynamic registration) {
|
||||
super.customizeRegistration(registration);
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.baeldung.spring;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.webflow.config.AbstractFlowConfiguration;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator;
|
||||
|
||||
@Configuration
|
||||
public class WebFlowConfig extends AbstractFlowConfiguration {
|
||||
|
||||
@Autowired
|
||||
private WebMvcConfig webMvcConfig;
|
||||
|
||||
@Bean
|
||||
public FlowDefinitionRegistry flowRegistry() {
|
||||
return getFlowDefinitionRegistryBuilder(flowBuilderServices()).addFlowLocation("/WEB-INF/flows/activation-flow.xml", "activationFlow").build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowExecutor flowExecutor() {
|
||||
return getFlowExecutorBuilder(flowRegistry()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowBuilderServices flowBuilderServices() {
|
||||
return getFlowBuilderServicesBuilder().setViewFactoryCreator(mvcViewFactoryCreator()).setDevelopmentMode(true).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MvcViewFactoryCreator mvcViewFactoryCreator() {
|
||||
MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
|
||||
factoryCreator.setViewResolvers(Collections.singletonList(this.webMvcConfig.viewResolver()));
|
||||
factoryCreator.setUseSpringBeanBinding(true);
|
||||
return factoryCreator;
|
||||
}
|
||||
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package com.baeldung.spring;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
import org.springframework.web.servlet.view.JstlView;
|
||||
import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
|
||||
import org.springframework.webflow.mvc.servlet.FlowHandlerMapping;
|
||||
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
private WebFlowConfig webFlowConfig;
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public InternalResourceViewResolver viewResolver() {
|
||||
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
|
||||
viewResolver.setViewClass(JstlView.class);
|
||||
viewResolver.setPrefix("/WEB-INF/view/");
|
||||
viewResolver.setSuffix(".jsp");
|
||||
return viewResolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowHandlerMapping flowHandlerMapping() {
|
||||
FlowHandlerMapping handlerMapping = new FlowHandlerMapping();
|
||||
handlerMapping.setOrder(-1);
|
||||
handlerMapping.setFlowRegistry(this.webFlowConfig.flowRegistry());
|
||||
return handlerMapping;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowHandlerAdapter flowHandlerAdapter() {
|
||||
FlowHandlerAdapter handlerAdapter = new FlowHandlerAdapter();
|
||||
handlerAdapter.setFlowExecutor(this.webFlowConfig.flowExecutor());
|
||||
handlerAdapter.setSaveOutputToFlashScopeOnRedirect(true);
|
||||
return handlerAdapter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?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:flow="http://www.springframework.org/schema/webflow-config"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/webflow-config
|
||||
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.4.xsd
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||
|
||||
|
||||
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
|
||||
<property name="flowRegistry" ref="activationFlowRegistry"/>
|
||||
</bean>
|
||||
|
||||
<flow:flow-builder-services id="flowBuilderServices"
|
||||
view-factory-creator="mvcViewFactoryCreator"/>
|
||||
|
||||
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
|
||||
<property name="viewResolvers" ref="jspViewResolver"/>
|
||||
</bean>
|
||||
|
||||
<flow:flow-registry id="activationFlowRegistry" flow-builder-services="flowBuilderServices">
|
||||
<flow:flow-location id="activationFlow" path="/WEB-INF/flows/activation-flow.xml"/>
|
||||
</flow:flow-registry>
|
||||
|
||||
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
|
||||
<property name="flowExecutor" ref="activationFlowExecutor"/>
|
||||
</bean>
|
||||
<flow:flow-executor id="activationFlowExecutor" flow-registry="activationFlowRegistry"/>
|
||||
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework" level="WARN" />
|
||||
<logger name="org.springframework.transaction" level="WARN" />
|
||||
|
||||
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
|
||||
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow xmlns="http://www.springframework.org/schema/webflow"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/webflow
|
||||
http://www.springframework.org/schema/webflow/spring-webflow.xsd">
|
||||
|
||||
|
||||
<view-state id="activation">
|
||||
<transition on="activate" to="success"/>
|
||||
<transition on="cancel" to="failure"/>
|
||||
</view-state>
|
||||
|
||||
<view-state id="success" />
|
||||
|
||||
<view-state id="failure" />
|
||||
|
||||
</flow>
|
||||
@@ -0,0 +1,23 @@
|
||||
<html>
|
||||
<body>
|
||||
<h2>Hello World!</h2>
|
||||
<%--<a href="${flowExecutionUrl}">Start</a>--%>
|
||||
<%--<input type="submit" name="_eventId_success" value="Proceed" />--%>
|
||||
<%--<input type="submit" name="_eventId_failure" value="Cancel" />--%>
|
||||
|
||||
<form method="post" action="${flowExecutionUrl}">
|
||||
|
||||
<input type="hidden" name="_eventId" value="activate">
|
||||
<input type="submit" value="Proceed" />
|
||||
|
||||
</form>
|
||||
|
||||
<form method="post" action="${flowExecutionUrl}">
|
||||
|
||||
<input type="hidden" name="_eventId" value="cancel">
|
||||
<input type="submit" value="Cancel" />
|
||||
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
<h2>Activation Failed</h2>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>This is the body of the sample view</h1>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
<h2>Activation Successful!</h2>
|
||||
</body>
|
||||
</html>
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.baeldung;
|
||||
|
||||
import com.baeldung.spring.WebFlowConfig;
|
||||
import com.baeldung.spring.WebMvcConfig;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = {WebFlowConfig.class, WebMvcConfig.class})
|
||||
@WebAppConfiguration
|
||||
public class SpringContextTest {
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
## Spring REST Angular
|
||||
|
||||
This module contains articles about REST APIs with Spring and Angular
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [Pagination with Spring REST and AngularJS table](https://www.baeldung.com/pagination-with-a-spring-rest-api-and-an-angularjs-table)
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-rest-angular</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>spring-rest-angular</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>spring-mock-mvc</artifactId>
|
||||
<version>${rest-assured.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>spring-rest-angular</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<guava.version>19.0</guava.version>
|
||||
<start-class>com.baeldung.web.main.Application</start-class>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.web.dao;
|
||||
|
||||
import com.baeldung.web.entity.Student;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface StudentRepository extends JpaRepository<Student, Long>
|
||||
{
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.baeldung.web.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Student implements Serializable {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public Student() {
|
||||
}
|
||||
|
||||
public Student(long id, String name, String gender, Integer age) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.gender = gender;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
@Id
|
||||
private long id;
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
@Column(nullable = false)
|
||||
private String gender;
|
||||
@Column(nullable = false)
|
||||
private Integer age;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getGender() {
|
||||
return gender;
|
||||
}
|
||||
|
||||
public void setGender(String gender) {
|
||||
this.gender = gender;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.web.exception;
|
||||
|
||||
public class MyResourceNotFoundException extends RuntimeException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 4088649120307193208L;
|
||||
|
||||
public MyResourceNotFoundException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public MyResourceNotFoundException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public MyResourceNotFoundException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MyResourceNotFoundException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.web.main;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.web.filter.ShallowEtagHeaderFilter;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableAutoConfiguration
|
||||
@Import(PersistenceConfig.class)
|
||||
public class Application implements WebMvcConfigurer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ShallowEtagHeaderFilter shallowEtagHeaderFilter() {
|
||||
return new ShallowEtagHeaderFilter();
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.baeldung.web.main;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
|
||||
@EnableJpaRepositories("com.baeldung.web.dao")
|
||||
@ComponentScan(basePackages = { "com.baeldung.web" })
|
||||
@EntityScan("com.baeldung.web.entity")
|
||||
@Configuration
|
||||
public class PersistenceConfig {
|
||||
|
||||
@Bean
|
||||
public JdbcTemplate getJdbcTemplate() {
|
||||
return new JdbcTemplate(dataSource());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
||||
EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL).build();
|
||||
return db;
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.web.rest;
|
||||
|
||||
import com.baeldung.web.entity.Student;
|
||||
import com.baeldung.web.exception.MyResourceNotFoundException;
|
||||
import com.baeldung.web.service.StudentService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class StudentDirectoryRestController {
|
||||
|
||||
@Autowired
|
||||
private StudentService service;
|
||||
|
||||
@RequestMapping(value = "/student/get", params = { "page", "size" }, method = RequestMethod.GET, produces = "application/json")
|
||||
public Page<Student> findPaginated(@RequestParam("page") int page, @RequestParam("size") int size) {
|
||||
|
||||
Page<Student> resultPage = service.findPaginated(page, size);
|
||||
if (page > resultPage.getTotalPages()) {
|
||||
throw new MyResourceNotFoundException();
|
||||
}
|
||||
return resultPage;
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.web.service;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
public interface IOperations<T> {
|
||||
|
||||
public Page<T> findPaginated(final int page, final int size);
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.baeldung.web.service;
|
||||
|
||||
import com.baeldung.web.entity.Student;
|
||||
|
||||
public interface StudentService extends IOperations<Student> {
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.web.service;
|
||||
|
||||
import com.baeldung.web.dao.StudentRepository;
|
||||
import com.baeldung.web.entity.Student;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class StudentServiceImpl implements StudentService {
|
||||
|
||||
@Autowired
|
||||
private StudentRepository dao;
|
||||
|
||||
@Override
|
||||
public Page<Student> findPaginated(int page, int size) {
|
||||
return dao.findAll(PageRequest.of(page, size));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
server.servlet.contextPath=/
|
||||
spring.h2.console.enabled=true
|
||||
logging.level.org.hibernate.SQL=info
|
||||
spring.jpa.generate-ddl=true
|
||||
spring.jpa.hibernate.ddl-auto=create
|
||||
@@ -0,0 +1,40 @@
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (1,'Bryan', 'Male',20);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (2, 'Ben', 'Male', 22);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (3,'Lisa', 'Female',24);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (4,'Sarah', 'Female',20);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (5,'Jay', 'Male',20);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (6,'John', 'Male',22);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (7,'Jordan', 'Male',24);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (8,'Rob', 'Male',26);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (9,'Will', 'Male',20);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (10,'Shawn', 'Male',22);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (11,'Taylor', 'Female',24);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (12,'Venus', 'Female',26);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (13,'Vince', 'Male',20);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (14,'Carol', 'Female',22);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (15,'Joana', 'Female',24);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (16,'Dion', 'Male',26);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (17,'Evans', 'Male',20);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (18,'Bart', 'Male',22);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (19,'Jenny', 'Female',24);
|
||||
INSERT INTO student (id,name,gender,age)
|
||||
VALUES (20,'Kristine', 'Female',26);
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
version="2.5">
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.html</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
</web-app>
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" ng-app="app">
|
||||
<head>
|
||||
<link rel="stylesheet"
|
||||
href="//cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.css">
|
||||
<script
|
||||
src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
|
||||
<script
|
||||
src="//cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.js"></script>
|
||||
<script src="view/app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div ng-controller="StudentCtrl as vm">
|
||||
<div ui-grid="gridOptions" class="grid" ui-grid-pagination></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,56 @@
|
||||
var app = angular.module('app', ['ui.grid','ui.grid.pagination']);
|
||||
|
||||
app.controller('StudentCtrl', ['$scope','StudentService', function ($scope,StudentService) {
|
||||
var paginationOptions = {
|
||||
pageNumber: 1,
|
||||
pageSize: 5,
|
||||
sort: null
|
||||
};
|
||||
|
||||
StudentService.getStudents(paginationOptions.pageNumber,
|
||||
paginationOptions.pageSize).success(function(data){
|
||||
$scope.gridOptions.data = data.content;
|
||||
$scope.gridOptions.totalItems = data.totalElements;
|
||||
});
|
||||
|
||||
$scope.gridOptions = {
|
||||
paginationPageSizes: [5, 10, 20],
|
||||
paginationPageSize: paginationOptions.pageSize,
|
||||
enableColumnMenus:false,
|
||||
useExternalPagination: true,
|
||||
columnDefs: [
|
||||
{ name: 'id' },
|
||||
{ name: 'name' },
|
||||
{ name: 'gender' },
|
||||
{ name: 'age' }
|
||||
],
|
||||
onRegisterApi: function(gridApi) {
|
||||
$scope.gridApi = gridApi;
|
||||
gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
|
||||
paginationOptions.pageNumber = newPage;
|
||||
paginationOptions.pageSize = pageSize;
|
||||
StudentService.getStudents(newPage,pageSize).success(function(data){
|
||||
$scope.gridOptions.data = data.content;
|
||||
$scope.gridOptions.totalItems = data.totalElements;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}]);
|
||||
|
||||
app.service('StudentService',['$http', function ($http) {
|
||||
|
||||
function getStudents(pageNumber,size) {
|
||||
pageNumber = pageNumber > 0?pageNumber - 1:0;
|
||||
return $http({
|
||||
method: 'GET',
|
||||
url: 'student/get?page='+pageNumber+'&size='+size
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getStudents:getStudents
|
||||
};
|
||||
|
||||
}]);
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.baeldung;
|
||||
|
||||
import com.baeldung.web.main.Application;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
public class SpringContextTest {
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package com.baeldung.web.service;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsCollectionContaining.hasItems;
|
||||
import static org.hamcrest.core.IsEqual.equalTo;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import com.baeldung.web.main.Application;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class StudentServiceIntegrationTest {
|
||||
|
||||
@LocalServerPort
|
||||
int port;
|
||||
|
||||
private static final String ENDPOINT = "http://localhost:%s/student/get";
|
||||
|
||||
@Test
|
||||
public void givenRequestForStudents_whenPageIsOne_expectContainsNames() {
|
||||
given().params("page", "0", "size", "2").get(String.format(ENDPOINT, port)).then().assertThat()
|
||||
.body("content.name", hasItems("Bryan", "Ben"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequestForStudents_whenSizeIsTwo_expectTwoItems() {
|
||||
given().params("page", "0", "size", "2").get(String.format(ENDPOINT, port)).then().assertThat().body("size", equalTo(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequestForStudents_whenSizeIsTwo_expectNumberOfElementsTwo() {
|
||||
given().params("page", "0", "size", "2").get(String.format(ENDPOINT, port)).then().assertThat().body("numberOfElements", equalTo(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequestForStudents_whenResourcesAreRetrievedPaged_thenExpect200() {
|
||||
given().params("page", "0", "size", "2").get(String.format(ENDPOINT, port)).then().statusCode(200);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequestForStudents_whenPageOfResourcesAreRetrievedOutOfBounds_thenExpect500() {
|
||||
given().params("page", "1000", "size", "2").get(String.format(ENDPOINT, port)).then().statusCode(500);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequestForStudents_whenPageNotValid_thenExpect500() {
|
||||
given().params("page", RandomStringUtils.randomNumeric(5), "size", "2").get(String.format(ENDPOINT, port)).then().statusCode(500);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequestForStudents_whenPageSizeIsFive_expectFiveItems() {
|
||||
given().params("page", "0", "size", "5").get(String.format(ENDPOINT, port)).then().body("content.size()", is(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() {
|
||||
given().params("page", "0", "size", "2").get(String.format(ENDPOINT, port)).then().assertThat().body("first", equalTo(true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
## Spring RestTemplate
|
||||
|
||||
This module contains articles about Spring RestTemplate
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [Spring RestTemplate Request/Response Logging](https://www.baeldung.com/spring-resttemplate-logging)
|
||||
- [Proxies With RestTemplate](https://www.baeldung.com/java-resttemplate-proxy)
|
||||
- [A Custom Media Type for a Spring REST API](https://www.baeldung.com/spring-rest-custom-media-type)
|
||||
- [RestTemplate Post Request with JSON](https://www.baeldung.com/spring-resttemplate-post-json)
|
||||
- [How to Compress Requests Using the Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-compressing-requests)
|
||||
- [Get list of JSON objects with Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-json-list)
|
||||
@@ -0,0 +1,86 @@
|
||||
<?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>
|
||||
<artifactId>spring-resttemplate-2</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>spring-resttemplate-2</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>parent-boot-2/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring Boot Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jetty</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.compress;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class CompressingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CompressingClientHttpRequestInterceptor.class);
|
||||
|
||||
private static final String GZIP_ENCODING = "gzip";
|
||||
|
||||
/**
|
||||
* Compress a request body using Gzip and add Http headers.
|
||||
*
|
||||
* @param req
|
||||
* @param body
|
||||
* @param exec
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest req, byte[] body, ClientHttpRequestExecution exec)
|
||||
throws IOException {
|
||||
LOG.info("Compressing request...");
|
||||
HttpHeaders httpHeaders = req.getHeaders();
|
||||
httpHeaders.add(HttpHeaders.CONTENT_ENCODING, GZIP_ENCODING);
|
||||
httpHeaders.add(HttpHeaders.ACCEPT_ENCODING, GZIP_ENCODING);
|
||||
return exec.execute(req, GzipUtils.compress(body));
|
||||
}
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.baeldung.compress;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
public class GzipUtils {
|
||||
|
||||
/**
|
||||
* Gzip a string.
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static byte[] compress(String text) throws Exception {
|
||||
return GzipUtils.compress(text.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gzip a byte array.
|
||||
*
|
||||
* @param body
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static byte[] compress(byte[] body) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos)) {
|
||||
gzipOutputStream.write(body);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress a Gzipped byte array to a String.
|
||||
*
|
||||
* @param body
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String decompress(byte[] body) throws IOException {
|
||||
try (GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(body))) {
|
||||
return IOUtils.toString(gzipInputStream, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.compress;
|
||||
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
|
||||
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Configure Jetty web server so it handles compressed requests.
|
||||
*/
|
||||
@Configuration
|
||||
public class JettyWebServerConfiguration {
|
||||
|
||||
private static final int MIN_BYTES = 1;
|
||||
|
||||
/**
|
||||
* Customise the Jetty web server to automatically decompress requests.
|
||||
*/
|
||||
@Bean
|
||||
public JettyServletWebServerFactory jettyServletWebServerFactory() {
|
||||
|
||||
JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
|
||||
factory.addServerCustomizers(server -> {
|
||||
|
||||
GzipHandler gzipHandler = new GzipHandler();
|
||||
// Enable request decompression
|
||||
gzipHandler.setInflateBufferSize(MIN_BYTES);
|
||||
gzipHandler.setHandler(server.getHandler());
|
||||
|
||||
HandlerCollection handlerCollection = new HandlerCollection(gzipHandler);
|
||||
server.setHandler(handlerCollection);
|
||||
});
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.compress;
|
||||
|
||||
public class Message {
|
||||
|
||||
private String text;
|
||||
|
||||
public Message() {
|
||||
}
|
||||
|
||||
public Message(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("Message {");
|
||||
sb.append("text='").append(text).append('\'');
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.compress;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
public class MessageController {
|
||||
|
||||
protected static final String PROCESSED = "Processed ";
|
||||
|
||||
protected static final String REQUEST_MAPPING = "process";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MessageController.class);
|
||||
|
||||
/**
|
||||
* A simple endpoint that responds with "Processed " + supplied Message content.
|
||||
*
|
||||
* @param headers
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = REQUEST_MAPPING)
|
||||
public ResponseEntity<String> processMessage(@RequestHeader Map<String, String> headers,
|
||||
@RequestBody Message message) {
|
||||
|
||||
// Print headers
|
||||
headers.forEach((k, v) -> LOG.info(k + "=" + v));
|
||||
|
||||
return ResponseEntity.ok(PROCESSED + message.getText());
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.compress;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfiguration {
|
||||
|
||||
/**
|
||||
* A RestTemplate that compresses requests.
|
||||
*
|
||||
* @return RestTemplate
|
||||
*/
|
||||
@Bean
|
||||
public RestTemplate getRestTemplate() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.getInterceptors().add(new CompressingClientHttpRequestInterceptor());
|
||||
return restTemplate;
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.compress;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableAutoConfiguration
|
||||
public class SpringCompressRequestApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringCompressRequestApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.resttemplate;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class RestTemplateConfigurationApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(RestTemplateConfigurationApplication.class, args);
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.resttemplate.json.consumer.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UserConsumerService {
|
||||
|
||||
List<String> processUserDataFromObjectArray();
|
||||
|
||||
List<String> processUserDataFromUserArray();
|
||||
|
||||
List<String> processUserDataFromUserList();
|
||||
|
||||
List<String> processNestedUserDataFromUserArray();
|
||||
|
||||
List<String> processNestedUserDataFromUserList();
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package com.baeldung.resttemplate.json.consumer.service;
|
||||
|
||||
import com.baeldung.resttemplate.json.model.Address;
|
||||
import com.baeldung.resttemplate.json.model.User;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class UserConsumerServiceImpl implements UserConsumerService {
|
||||
|
||||
private static final String BASE_URL = "http://localhost:8080/users";
|
||||
private final RestTemplate restTemplate;
|
||||
private static final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
public UserConsumerServiceImpl(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> processUserDataFromObjectArray() {
|
||||
ResponseEntity<Object[]> responseEntity = restTemplate.getForEntity(BASE_URL, Object[].class);
|
||||
Object[] objects = responseEntity.getBody();
|
||||
return Arrays.stream(objects)
|
||||
.map(object -> mapper.convertValue(object, User.class))
|
||||
.map(User::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> processUserDataFromUserArray() {
|
||||
ResponseEntity<User[]> responseEntity = restTemplate.getForEntity(BASE_URL, User[].class);
|
||||
User[] userArray = responseEntity.getBody();
|
||||
return Arrays.stream(userArray)
|
||||
.map(User::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> processUserDataFromUserList() {
|
||||
ResponseEntity<List<User>> responseEntity =
|
||||
restTemplate.exchange(
|
||||
BASE_URL,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<List<User>>() {}
|
||||
);
|
||||
List<User> users = responseEntity.getBody();
|
||||
return users.stream()
|
||||
.map(User::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> processNestedUserDataFromUserArray() {
|
||||
ResponseEntity<User[]> responseEntity = restTemplate.getForEntity(BASE_URL, User[].class);
|
||||
User[] userArray = responseEntity.getBody();
|
||||
//we can get more info if we need :
|
||||
MediaType contentType = responseEntity.getHeaders().getContentType();
|
||||
HttpStatus statusCode = responseEntity.getStatusCode();
|
||||
|
||||
return Arrays.stream(userArray)
|
||||
.flatMap(user -> user.getAddressList().stream())
|
||||
.map(Address::getPostCode)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> processNestedUserDataFromUserList() {
|
||||
ResponseEntity<List<User>> responseEntity =
|
||||
restTemplate.exchange(
|
||||
BASE_URL,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<List<User>>() {}
|
||||
);
|
||||
List<User> userList = responseEntity.getBody();
|
||||
return userList.stream()
|
||||
.flatMap(user -> user.getAddressList().stream())
|
||||
.map(Address::getPostCode)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.resttemplate.json.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class Address {
|
||||
private final String addressLine1;
|
||||
private final String addressLine2;
|
||||
private final String town;
|
||||
private final String postCode;
|
||||
|
||||
@JsonCreator
|
||||
public Address(
|
||||
@JsonProperty("addressLine1") String addressLine1,
|
||||
@JsonProperty("addressLine2") String addressLine2,
|
||||
@JsonProperty("town") String town,
|
||||
@JsonProperty("postCode") String postCode) {
|
||||
this.addressLine1 = addressLine1;
|
||||
this.addressLine2 = addressLine2;
|
||||
this.town = town;
|
||||
this.postCode = postCode;
|
||||
}
|
||||
public String getPostCode() {
|
||||
return postCode;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.resttemplate.json.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class User {
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final List<Address> addressList;
|
||||
|
||||
@JsonCreator
|
||||
public User(
|
||||
@JsonProperty("id") int id,
|
||||
@JsonProperty("name") String name,
|
||||
@JsonProperty("addressList") List<Address> addressList) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.addressList = addressList;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<Address> getAddressList() { return addressList; }
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.resttemplate.logging.web.controller;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class PersonController {
|
||||
|
||||
@PostMapping("/persons")
|
||||
public List<String> getPersons() {
|
||||
return Arrays.asList(new String[] { "Lucie", "Jackie", "Danesh", "Tao" });
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.resttemplate.web.controller;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.baeldung.resttemplate.web.service.PersonService;
|
||||
import com.baeldung.resttemplate.web.dto.Person;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
|
||||
@RestController
|
||||
public class PersonAPI {
|
||||
|
||||
@Autowired
|
||||
private PersonService personService;
|
||||
|
||||
@GetMapping("/")
|
||||
public String home() {
|
||||
return "Spring boot is working!";
|
||||
}
|
||||
|
||||
@PostMapping(value = "/createPerson", consumes = "application/json", produces = "application/json")
|
||||
public Person createPerson(@RequestBody Person person) {
|
||||
return personService.saveUpdatePerson(person);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/updatePerson", consumes = "application/json", produces = "application/json")
|
||||
public Person updatePerson(@RequestBody Person person, HttpServletResponse response) {
|
||||
response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentContextPath()
|
||||
.path("/findPerson/" + person.getId())
|
||||
.toUriString());
|
||||
return personService.saveUpdatePerson(person);
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.resttemplate.web.dto;
|
||||
|
||||
public class Person {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
public Person() {
|
||||
|
||||
}
|
||||
|
||||
public Person(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.baeldung.resttemplate.web.service;
|
||||
|
||||
import com.baeldung.resttemplate.web.dto.Person;
|
||||
|
||||
public interface PersonService {
|
||||
|
||||
public Person saveUpdatePerson(Person person);
|
||||
|
||||
public Person findPersonById(Integer id);
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.resttemplate.web.service;
|
||||
|
||||
import com.baeldung.resttemplate.web.dto.Person;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class PersonServiceImpl implements PersonService {
|
||||
|
||||
@Override
|
||||
public Person saveUpdatePerson(Person person) {
|
||||
return person;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Person findPersonById(Integer id) {
|
||||
return new Person(id, "John");
|
||||
}
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.sampleapp.config;
|
||||
|
||||
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.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ComponentScan({ "com.baeldung.sampleapp.web" })
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
public WebConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.sampleapp.web.controller.mediatypes;
|
||||
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
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.RestController;
|
||||
|
||||
import com.baeldung.sampleapp.web.dto.BaeldungItem;
|
||||
import com.baeldung.sampleapp.web.dto.BaeldungItemV2;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/", produces = "application/vnd.baeldung.api.v1+json")
|
||||
public class CustomMediaTypeController {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/public/api/items/{id}", produces = "application/vnd.baeldung.api.v1+json")
|
||||
public @ResponseBody BaeldungItem getItem(@PathVariable("id") String id) {
|
||||
return new BaeldungItem("itemId1");
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/public/api/items/{id}", produces = "application/vnd.baeldung.api.v2+json")
|
||||
public @ResponseBody BaeldungItemV2 getItemSecondAPIVersion(@PathVariable("id") String id) {
|
||||
return new BaeldungItemV2("itemName");
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.sampleapp.web.dto;
|
||||
|
||||
public class BaeldungItem {
|
||||
private final String itemId;
|
||||
|
||||
public BaeldungItem(String itemId) {
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
public String getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.sampleapp.web.dto;
|
||||
|
||||
|
||||
public class BaeldungItemV2 {
|
||||
private final String itemName;
|
||||
|
||||
public BaeldungItemV2(String itemName) {
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
public String getItemName() {
|
||||
return itemName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
server.port=8080
|
||||
server.servlet.context-path=/spring-rest
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.compress;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class GzipUtilsUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenCompressedText_whenDecompressed_thenSuccessful() throws Exception {
|
||||
final String expectedText = "Hello Baeldung!";
|
||||
byte[] compressedText = GzipUtils.compress(expectedText);
|
||||
String decompressedText = GzipUtils.decompress(compressedText);
|
||||
assertNotNull(compressedText);
|
||||
assertEquals(expectedText, decompressedText);
|
||||
}
|
||||
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.compress;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class MessageControllerUnitTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MessageControllerUnitTest.class);
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@LocalServerPort
|
||||
private int randomServerPort;
|
||||
|
||||
/**
|
||||
* As a further test you can intercept the request body, using a tool like
|
||||
* Wireshark, to see the request body is actually gzipped.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void givenRestTemplate_whenPostCompressedRequest_thenRespondsSuccessfully() throws Exception {
|
||||
|
||||
final String text = "Hello Baeldung!";
|
||||
Message message = new Message(text);
|
||||
|
||||
HttpEntity<Message> request = new HttpEntity<>(message);
|
||||
String uri = String.format("http://localhost:%s/%s", randomServerPort, MessageController.REQUEST_MAPPING);
|
||||
|
||||
ResponseEntity<String> responseEntity = restTemplate.postForEntity(uri, request, String.class);
|
||||
|
||||
String response = responseEntity.getBody();
|
||||
LOG.info("Got response [{}]", response);
|
||||
|
||||
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||
assertNotNull(response);
|
||||
assertEquals(MessageController.PROCESSED + text, response);
|
||||
}
|
||||
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
package com.baeldung.resttemplate.json.consumer.service;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.ExpectedCount;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
|
||||
|
||||
@SpringBootTest
|
||||
public class UserConsumerServiceImplUnitTest {
|
||||
|
||||
private static String USER_JSON = "[{\"id\":1,\"name\":\"user1\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user1_address1_postCode\"}," +
|
||||
"{\"addressLine1\":\"address2_addressLine1\",\"addressLine2\":\"address2_addressLine2\",\"town\":\"address2_town\",\"postCode\":\"user1_address2_postCode\"}]}," +
|
||||
"{\"id\":2,\"name\":\"user2\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user2_address1_postCode\"}]}]";
|
||||
|
||||
private MockRestServiceServer mockServer;
|
||||
private final RestTemplate restTemplate = new RestTemplate();
|
||||
private final UserConsumerService tested = new UserConsumerServiceImpl(restTemplate);
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
mockServer = MockRestServiceServer.createServer(restTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenProcessUserDataAsObjects_thenOK() {
|
||||
String url = "http://localhost:8080/users";
|
||||
List<String> expected = Arrays.asList("user1", "user2");
|
||||
|
||||
mockServer.expect(ExpectedCount.once(),
|
||||
requestTo(url))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withStatus(HttpStatus.OK)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(USER_JSON));
|
||||
|
||||
List<String> actual = tested.processUserDataFromObjectArray();
|
||||
|
||||
mockServer.verify();
|
||||
assertThat(actual).containsExactly(expected.get(0), expected.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenProcessUserDataAsArray_thenOK() {
|
||||
String url = "http://localhost:8080/users";
|
||||
List<String> expected = Arrays.asList("user1", "user2");
|
||||
|
||||
mockServer.expect(ExpectedCount.once(),
|
||||
requestTo(url))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withStatus(HttpStatus.OK)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(USER_JSON));
|
||||
|
||||
List<String> actual = tested.processUserDataFromUserArray();
|
||||
|
||||
mockServer.verify();
|
||||
assertThat(actual).containsExactly(expected.get(0), expected.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenProcessUserDataAsList_thenOK() {
|
||||
String url = "http://localhost:8080/users";
|
||||
List<String> expected = Arrays.asList("user1", "user2");
|
||||
|
||||
mockServer.expect(ExpectedCount.once(),
|
||||
requestTo(url))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withStatus(HttpStatus.OK)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(USER_JSON));
|
||||
|
||||
List<String> actual = tested.processUserDataFromUserList();
|
||||
|
||||
mockServer.verify();
|
||||
assertThat(actual).containsExactly(expected.get(0), expected.get(1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenProcessNestedUserDataFromArray_thenOK() {
|
||||
String url = "http://localhost:8080/users";
|
||||
List<String> expected = Arrays.asList("user1_address1_postCode", "user1_address2_postCode", "user2_address1_postCode");
|
||||
|
||||
mockServer.expect(ExpectedCount.once(),
|
||||
requestTo(url))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withStatus(HttpStatus.OK)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(USER_JSON));
|
||||
|
||||
List<String> actual = tested.processNestedUserDataFromUserArray();
|
||||
|
||||
mockServer.verify();
|
||||
assertThat(actual).containsExactly(expected.get(0), expected.get(1), expected.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenProcessNestedUserDataFromList_thenOK() {
|
||||
String url = "http://localhost:8080/users";
|
||||
List<String> expected = Arrays.asList("user1_address1_postCode", "user1_address2_postCode", "user2_address1_postCode");
|
||||
|
||||
mockServer.expect(ExpectedCount.once(),
|
||||
requestTo(url))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withStatus(HttpStatus.OK)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(USER_JSON));
|
||||
|
||||
List<String> actual = tested.processNestedUserDataFromUserList();
|
||||
|
||||
mockServer.verify();
|
||||
assertThat(actual).containsExactly(expected.get(0), expected.get(1), expected.get(2));
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.resttemplate.logging;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.stream.Collectors;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
public class LoggingInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
final static Logger LOGGER = LoggerFactory.getLogger(LoggingInterceptor.class);
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest req, byte[] reqBody, ClientHttpRequestExecution ex) throws IOException {
|
||||
LOGGER.debug("Request body: {}", new String(reqBody, StandardCharsets.UTF_8));
|
||||
ClientHttpResponse response = ex.execute(req, reqBody);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
InputStreamReader isr = new InputStreamReader(response.getBody(), StandardCharsets.UTF_8);
|
||||
String body = new BufferedReader(isr).lines()
|
||||
.collect(Collectors.joining("\n"));
|
||||
LOGGER.debug("Response body: {}", body);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package com.baeldung.resttemplate.logging;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.http.client.BufferingClientHttpRequestFactory;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class RestTemplateLoggingLiveTest {
|
||||
|
||||
private static final String baseUrl = "http://localhost:8080/spring-rest";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RestTemplateLoggingLiveTest.class);
|
||||
|
||||
@Test
|
||||
public void givenHttpClientConfiguration_whenSendGetForRequestEntity_thenRequestResponseFullLog() {
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
|
||||
|
||||
final ResponseEntity<String> response = restTemplate.postForEntity(baseUrl + "/persons", "my request body", String.class);
|
||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||
assertEquals("[\"Lucie\",\"Jackie\",\"Danesh\",\"Tao\"]", response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoggingInterceptorConfiguration_whenSendGetForRequestEntity_thenRequestResponseCustomLog() {
|
||||
|
||||
RestTemplate restTemplate = null;
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(
|
||||
new SimpleClientHttpRequestFactory());
|
||||
restTemplate = new RestTemplate(factory);
|
||||
} else {
|
||||
restTemplate = new RestTemplate();
|
||||
}
|
||||
|
||||
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
|
||||
if (CollectionUtils.isEmpty(interceptors)) {
|
||||
interceptors = new ArrayList<>();
|
||||
}
|
||||
interceptors.add(new LoggingInterceptor());
|
||||
restTemplate.setInterceptors(interceptors);
|
||||
|
||||
final ResponseEntity<String> response = restTemplate.postForEntity(baseUrl + "/persons", "my request body", String.class);
|
||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||
assertEquals("[\"Lucie\",\"Jackie\",\"Danesh\",\"Tao\"]", response.getBody());
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package com.baeldung.resttemplate.postjson;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import com.baeldung.resttemplate.RestTemplateConfigurationApplication;
|
||||
import com.baeldung.resttemplate.web.dto.Person;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = RestTemplateConfigurationApplication.class)
|
||||
public class PersonAPILiveTest {
|
||||
|
||||
private static String createPersonUrl;
|
||||
private static String updatePersonUrl;
|
||||
|
||||
private static RestTemplate restTemplate;
|
||||
|
||||
private static HttpHeaders headers;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private static JSONObject personJsonObject;
|
||||
|
||||
@BeforeClass
|
||||
public static void runBeforeAllTestMethods() throws JSONException {
|
||||
createPersonUrl = "http://localhost:8082/spring-rest/createPerson";
|
||||
updatePersonUrl = "http://localhost:8082/spring-rest/updatePerson";
|
||||
|
||||
restTemplate = new RestTemplate();
|
||||
|
||||
headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
personJsonObject = new JSONObject();
|
||||
personJsonObject.put("id", 1);
|
||||
personJsonObject.put("name", "John");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDataIsJson_whenDataIsPostedByPostForObject_thenResponseBodyIsNotNull() throws IOException {
|
||||
HttpEntity<String> request = new HttpEntity<String>(personJsonObject.toString(), headers);
|
||||
String personResultAsJsonStr = restTemplate.postForObject(createPersonUrl, request, String.class);
|
||||
JsonNode root = objectMapper.readTree(personResultAsJsonStr);
|
||||
|
||||
Person person = restTemplate.postForObject(createPersonUrl, request, Person.class);
|
||||
|
||||
assertNotNull(personResultAsJsonStr);
|
||||
assertNotNull(root);
|
||||
assertNotNull(root.path("name")
|
||||
.asText());
|
||||
|
||||
assertNotNull(person);
|
||||
assertNotNull(person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDataIsJson_whenDataIsPostedByPostForEntity_thenResponseBodyIsNotNull() throws IOException {
|
||||
HttpEntity<String> request = new HttpEntity<String>(personJsonObject.toString(), headers);
|
||||
ResponseEntity<String> responseEntityStr = restTemplate.postForEntity(createPersonUrl, request, String.class);
|
||||
JsonNode root = objectMapper.readTree(responseEntityStr.getBody());
|
||||
|
||||
ResponseEntity<Person> responseEntityPerson = restTemplate.postForEntity(createPersonUrl, request, Person.class);
|
||||
|
||||
assertNotNull(responseEntityStr.getBody());
|
||||
assertNotNull(root.path("name")
|
||||
.asText());
|
||||
|
||||
assertNotNull(responseEntityPerson.getBody());
|
||||
assertNotNull(responseEntityPerson.getBody()
|
||||
.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDataIsJson_whenDataIsPostedByPostForLocation_thenResponseBodyIsTheLocationHeader() throws JsonProcessingException {
|
||||
HttpEntity<String> request = new HttpEntity<String>(personJsonObject.toString(), headers);
|
||||
URI locationHeader = restTemplate.postForLocation(updatePersonUrl, request);
|
||||
|
||||
assertNotNull(locationHeader);
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.resttemplate.proxy;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.Proxy.Type;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* This class is used to test a request using {@link RestTemplate} with {@link Proxy}
|
||||
* using a {@link SimpleClientHttpRequestFactory} as configuration.
|
||||
* <br />
|
||||
* <br />
|
||||
*
|
||||
* Before running the test we should change the <code>PROXY_SERVER_HOST</code>
|
||||
* and <code>PROXY_SERVER_PORT</code> constants in our class to match our preferred proxy configuration.
|
||||
*/
|
||||
public class RequestFactoryLiveTest {
|
||||
|
||||
private static final String PROXY_SERVER_HOST = "127.0.0.1";
|
||||
private static final int PROXY_SERVER_PORT = 8080;
|
||||
|
||||
RestTemplate restTemplate;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress(PROXY_SERVER_HOST, PROXY_SERVER_PORT));
|
||||
|
||||
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
|
||||
requestFactory.setProxy(proxy);
|
||||
|
||||
restTemplate = new RestTemplate(requestFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRestTemplate_whenRequestedWithProxy_thenResponseBodyIsOk() {
|
||||
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://httpbin.org/get", String.class);
|
||||
|
||||
assertThat(responseEntity.getStatusCode(), is(equalTo(HttpStatus.OK)));
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.baeldung.resttemplate.proxy;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.Proxy;
|
||||
|
||||
import org.apache.http.HttpException;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.boot.web.client.RestTemplateCustomizer;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* This class is used to test a request using {@link RestTemplate} with {@link Proxy}
|
||||
* using a {@link RestTemplateCustomizer} as configuration.
|
||||
* <br />
|
||||
* <br />
|
||||
*
|
||||
* Before running the test we should change the <code>PROXY_SERVER_HOST</code>
|
||||
* and <code>PROXY_SERVER_PORT</code> constants in our class to match our preferred proxy configuration.
|
||||
*/
|
||||
public class RestTemplateCustomizerLiveTest {
|
||||
|
||||
private static final String PROXY_SERVER_HOST = "127.0.0.1";
|
||||
private static final int PROXY_SERVER_PORT = 8080;
|
||||
|
||||
RestTemplate restTemplate;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
restTemplate = new RestTemplateBuilder(new ProxyCustomizer()).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRestTemplate_whenRequestedWithProxy_thenResponseBodyIsOk() {
|
||||
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://httpbin.org/get", String.class);
|
||||
|
||||
assertThat(responseEntity.getStatusCode(), is(equalTo(HttpStatus.OK)));
|
||||
}
|
||||
|
||||
private static class ProxyCustomizer implements RestTemplateCustomizer {
|
||||
|
||||
@Override
|
||||
public void customize(RestTemplate restTemplate) {
|
||||
HttpHost proxy = new HttpHost(PROXY_SERVER_HOST, PROXY_SERVER_PORT);
|
||||
HttpClient httpClient = HttpClientBuilder.create()
|
||||
.setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {
|
||||
@Override
|
||||
public HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
|
||||
return super.determineProxy(target, request, context);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.baeldung.web.controller.mediatypes;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.baeldung.sampleapp.config.WebConfig;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = WebConfig.class)
|
||||
@WebAppConfiguration
|
||||
public class CustomMediaTypeControllerIntegrationTest {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext webApplicationContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenServiceUrl_whenGetWithProperAcceptHeaderFirstAPIVersion_thenReturn200() throws Exception {
|
||||
mockMvc.perform(get("/public/api/items/1").accept("application/vnd.baeldung.api.v1+json")).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenServiceUrl_whenGetWithProperAcceptHeaderSecondVersion_thenReturn200() throws Exception {
|
||||
mockMvc.perform(get("/public/api/items/2").accept("application/vnd.baeldung.api.v2+json")).andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.baeldung.web.controller.mediatypes;
|
||||
|
||||
import io.restassured.http.ContentType;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = {TestConfig.class}, loader = AnnotationConfigContextLoader.class)
|
||||
public class CustomMediaTypeControllerLiveTest {
|
||||
private static final String URL_PREFIX = "http://localhost:8082/spring-rest";
|
||||
|
||||
@Test
|
||||
public void givenServiceEndpoint_whenGetRequestFirstAPIVersion_thenShouldReturn200() {
|
||||
given()
|
||||
.accept("application/vnd.baeldung.api.v1+json")
|
||||
.when()
|
||||
.get(URL_PREFIX + "/public/api/items/1")
|
||||
.then()
|
||||
.contentType(ContentType.JSON).and().statusCode(200);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenServiceEndpoint_whenGetRequestSecondAPIVersion_thenShouldReturn200() {
|
||||
given()
|
||||
.accept("application/vnd.baeldung.api.v2+json")
|
||||
.when()
|
||||
.get(URL_PREFIX + "/public/api/items/2")
|
||||
.then()
|
||||
.contentType(ContentType.JSON).and().statusCode(200);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user