The problem is that my resources for webapp are missing for springboot application build with maven as jar. I think that I have messed something up and after a googling session, I am still out of ideas how to solve a problem of
There was an unexpected error (type=Not Found, status=404).
/WEB-INF/static/index.html
after going to localhost:8080/login from jar.
Mvn build:
<build>
<resources>
<resource>
<directory>src/main/webapp/</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Here is my eclipse project structure:
Besides, I have a configuration class
#EnableWebMvc
#Configuration
#ComponentScan({ "com.staszkox.*" })
#Import({ SecurityConfiguration.class })
public class ResourcesResolver extends WebMvcConfigurerAdapter
{
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/static/");
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
{
configurer.enable();
}
}
#Controller
public class ResourcesController
{
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(#RequestParam(value = "error", required = false) String error,
#RequestParam(value = "logout", required = false) String logout)
{
return "index.html";
}
}
Do you have any ideas what could be wrong here? I have tried every resources folder setup in target folder with jar and still nothing. Everything works fine, if I run the application from eclipse.
Related
Seeing routing issues in my React/SpingBoot application.
Homepage (localhost:7070) loads correctly, however, I see issues when trying to route to /app (localhost:7070/app)
Any pointers?
App.java
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class})
#SpringBootApplication
public class App extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(App.class);
}
public static void main(final String[] args) throws Exception {
SpringApplication.run(App.class, args);
}
}
App.js
import React from "react";
import { ReactKeycloakProvider } from "#react-keycloak/web";
import keycloak from "./Keycloak";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Nav from "./components/Nav";
import WelcomePage from "./pages/Homepage";
import SecuredPage from "./pages/Securedpage";
import PrivateRoutes from "./helpers/PrivateRoutes";
function App() {
return (
<div>
<ReactKeycloakProvider authClient={keycloak}>
<Nav />
<BrowserRouter>
<Routes>
<Route path="/" element={<WelcomePage />}>
<Route path="app" element={ <SecuredPage />} />
</Route>
</Routes>
</BrowserRouter>
</ReactKeycloakProvider>
</div>
);
}
export default App;
Project Structure
Part of pom.xml
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/static</outputDirectory>
<resources>
<resource>
<directory>src/main/webapp/build</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Switched from HashRouter to BrowserRouter. Tried different nesting options for
I am making my first app with react and Spring security. I tried to learn with examples and tutorials online, namely he example from https://dzone.com/articles/integrating-spring-boot-and-react-with-spring-secu-1 into a WAR package (my requirement). It all works without security but when I add security my home page is blank and the console says 401 to every request. I want to show the login page which is not secured. I tried to use addResourceHandlers but it makes the matters only worse and shows 404. This config looks like this:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/")
.addResourceLocations("frontend/build/static/");
registry.addResourceHandler("/** .js")
.addResourceLocations("frontend/build/");
registry.addResourceHandler("/** .json")
.addResourceLocations("frontend/build/");
registry.addResourceHandler("/** .ico")
.addResourceLocations("frontend/build/");
registry.addResourceHandler("/index.html")
.addResourceLocations("frontend/build/index.html");
}
My web security config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class JWTWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtUnAuthorizedResponseAuthenticationEntryPoint jwtUnAuthorizedResponseAuthenticationEntryPoint;
#Autowired
private UserDetailsService jwtInMemoryUserDetailsService;
#Autowired
private JwtTokenAuthorizationOncePerRequestFilter jwtAuthenticationTokenFilter;
#Value("${jwt.get.token.uri}")
private String authenticationPath;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(jwtInMemoryUserDetailsService)
.passwordEncoder(passwordEncoderBean());
}
#Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(jwtUnAuthorizedResponseAuthenticationEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.anyRequest().authenticated();
httpSecurity
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
httpSecurity
.headers()
.frameOptions().sameOrigin() //H2 Console Needs this setting
.cacheControl(); //disable caching
}
#Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity
.ignoring()
.antMatchers(
HttpMethod.POST,
authenticationPath
)
.antMatchers(HttpMethod.OPTIONS, "/**")
.and()
.ignoring()
.antMatchers(
HttpMethod.GET,
"/" //Other Stuff You want to Ignore
)
.and()
.ignoring()
.antMatchers("/h2-console/**/**");//Should not be in Production!
}
}
My properties:
jwt.signing.key.secret=mySecret
jwt.get.token.uri=/authenticate
jwt.refresh.token.uri=/refresh
jwt.http.request.header=Authorization
jwt.token.expiration.in.seconds=604800
server.servlet.context-path=/Spring-Boot-React
my App.js:
class App extends Component {
render() {
return (
<div className="container">
<InstructorApp />
</div>
);
}
}
export default App;
and my InstructorApp:
class InstructorApp extends Component {
render() {
return (
<>
<Router basename="/Spring-Boot-React">
<>
<MenuComponent />
<Switch>
<Route path="/" exact component={LoginComponent} />
<Route path="/login" exact component={LoginComponent} />
<AuthenticatedRoute path="/logout" exact component={LogoutComponent} />
<AuthenticatedRoute path="/courses" exact component={ListCoursesComponent} />
</Switch>
</>
</Router>
</>
)
}
}
export default InstructorApp
with my main app which i based on this it's the same outcome but i first want to try to deploy this one from tutorials. The package names are different because I used another tutoruial where the war built correctly(the original has too different a pom).
My pom:
<?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>
<groupId>com.frugalis</groupId>
<artifactId>Spring-Boot-React</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Spring-Boot-React</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath />
<!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warSourceExcludes>
WEB-INF/view/react/node/**,
WEB-INF/view/react/node_modules/**,
WEB-INF/view/react/public/**,
WEB-INF/view/react/src/**,
WEB-INF/view/react/*
</warSourceExcludes>
</configuration>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.9.1</version>
<configuration>
<workingDirectory>frontend/</workingDirectory>
<installDirectory>target</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v12.14.0</nodeVersion>
<npmVersion>6.13.4</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<configuration>
<target>
<copy todir="${project.build.directory}/classes/static">
<fileset dir="${project.basedir}/frontend/build" />
</copy>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Controlers and mappings from the back end:
#RestController
#CrossOrigin(origins={ "http://localhost:3000", "http://localhost:4200" })
public class JwtAuthenticationRestController {
#Value("${jwt.http.request.header}")
private String tokenHeader;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Autowired
private UserDetailsService jwtInMemoryUserDetailsService;
#RequestMapping(value = "${jwt.get.token.uri}", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(#RequestBody JwtTokenRequest authenticationRequest)
throws AuthenticationException {
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
final UserDetails userDetails = jwtInMemoryUserDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new JwtTokenResponse(token));
}
#RequestMapping(value = "${jwt.refresh.token.uri}", method = RequestMethod.GET)
public ResponseEntity<?> refreshAndGetAuthenticationToken(HttpServletRequest request) {
String authToken = request.getHeader(tokenHeader);
final String token = authToken.substring(7);
String username = jwtTokenUtil.getUsernameFromToken(token);
JwtUserDetails user = (JwtUserDetails) jwtInMemoryUserDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.canTokenBeRefreshed(token)) {
String refreshedToken = jwtTokenUtil.refreshToken(token);
return ResponseEntity.ok(new JwtTokenResponse(refreshedToken));
} else {
return ResponseEntity.badRequest().body(null);
}
}
#ExceptionHandler({ AuthenticationException.class })
public ResponseEntity<String> handleAuthenticationException(AuthenticationException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage());
}
private void authenticate(String username, String password) {
Objects.requireNonNull(username);
Objects.requireNonNull(password);
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new AuthenticationException("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new AuthenticationException("INVALID_CREDENTIALS", e);
}
}
}
and
#CrossOrigin(origins = { "http://localhost:3000", "http://localhost:4200" })
#RestController
public class CourseResource {
#Autowired
private CoursesHardcodedService courseManagementService;
#GetMapping("/instructors/{username}/courses")
public List<Course> getAllCourses(#PathVariable String username) {
return courseManagementService.findAll();
}
}
My structure looks like this:
I'm having some difficulties importing a utility jar file containing some custom aspects into another project. It should be noted, that I'm not using Spring for this project, as my client is somewhat averse to Spring.
I have created a proof of concept (full code example below). When I run a test runner in the utility jar, any method annotated with my AspectJ annotation gets their aspects executed just fine. When I use the self-same jar in another project, the aspects are ignore.
When I run the main class in the utility I get:
$> java -cp aspectjrt-1.8.2.jar;aop-util-1.0-SNAPSHOT.jar TestOne
AspectOne's aroundAdvice's body is now executed Before aspectTestMethod is called.
Executing TestOne.aspectTestMethod()
AspectOne's aroundAdvice's body is now executed After aspectTestMethod is called.
If I run the main class of the consumer class, I get:
$>java -cp aspectjrt-1.8.2.jar;aop-util-1.0-SNAPSHOT.jar;aop-consumer-1.0-SNAPSHOT.jar Test
Test.testAspectOne
AspectTwo's aroundAdvice's body is now executed Before aspectTestMethod is called.
Test.testAspectTwo
AspectTwo's aroundAdvice's body is now executed After aspectTestMethod is called.
As I'm fairly new to aspect oriented programming, I'd really appreciate a pointer as to what I'm missing :)
utility jar
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sandbox.aop</groupId>
<artifactId>aop-util</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Annotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface AnnotationOne { }
Aspect
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.JoinPoint;
#Aspect
public class AspectOne {
#Pointcut("#annotation(AnnotationOne)")
public void annotationPointCutDefinition(){
}
#Pointcut("execution(* *(..))")
public void atExecution(){}
#Around("#annotation(AnnotationOne) && execution(* *(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
Object returnObject = null;
try {
System.out.println("AspectOne's aroundAdvice's body is now executed Before aspectTestMethod is called.");
returnObject = joinPoint.proceed();
} catch (Throwable throwable) {
throw throwable;
}
finally {
System.out.println("AspectOne's aroundAdvice's body is now executed After aspectTestMethod is called.");
}
return returnObject;
}
#After("annotationPointCutDefinition() && atExecution()")
public void printNewLine(JoinPoint pointcut){
System.out.print("\n\r");
}
}
Main class
public class TestOne {
public static void main(String[] args) {
TestOne testOne = new TestOne();
testOne.aspectTestMethod();
}
#AnnotationOne
public void aspectTestMethod(){
System.out.println("Executing TestOne.aspectTestMethod()");
}
}
AOP consumer
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sandbox.aop</groupId>
<artifactId>aop-consumer</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>sandbox.aop</groupId>
<artifactId>aop-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Annotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface AnnotationTwo {}
Aspect
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class AspectTwo {
#Pointcut("#annotation(AnnotationTwo)")
public void annotationPointCutDefinition(){
}
#Pointcut("execution(* *(..))")
public void atExecution(){}
#Around("#annotation(AnnotationTwo) && execution(* *(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
Object returnObject = null;
try {
System.out.println("AspectTwo's aroundAdvice's body is now executed Before aspectTestMethod is called.");
returnObject = joinPoint.proceed();
} catch (Throwable throwable) {
throw throwable;
}
finally {
System.out.println("AspectTwo's aroundAdvice's body is now executed After aspectTestMethod is called.");
}
return returnObject;
}
#After("annotationPointCutDefinition() && atExecution()")
public void printNewLine(JoinPoint pointcut){
System.out.print("\n\r");
}
}
Main class
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.testAspectOne();
test.testAspectTwo();
}
#AnnotationOne
public void testAspectOne() {
System.out.println(Test.class.getName() + ".testAspectOne");
}
#AnnotationTwo
public void testAspectTwo() {
System.out.println(Test.class.getName() + ".testAspectTwo");
}
}
You need to tell the aspectj weaver to weave aspect defined in your library using aspectLibraries:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<aspectLibraries>
<aspectLibrary>
<groupId>sandbox.aop</groupId>
<artifactId>aop-util</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
I want to run maven with different profile but it seems not working.
I created 2 differents java class for my JPAConfiguration :
JPAConfiguration.class and JPAConfigurationTest.class
#Configuration
#Profile({"dev"})
#EnableTransactionManagement(proxyTargetClass = true)
#EnableJpaRepositories(basePackages = { "com.jle.athleges.model.repository", "com.jle.athleges.security.repository" })
#ComponentScan(basePackages = { "com.jle.athleges.model.services", "com.jle.athleges.security.services" })
public class JpaConfiguration {
#Bean
public DataSource dataSource() throws SQLException {
System.out.println("use dev");
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
builder.setName("dev");
return builder.setType(EmbeddedDatabaseType.H2).build();
}
#Bean
public EntityManagerFactory entityManagerFactory() throws SQLException {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.jle.athleges.model.entity", "com.jle.athleges.security.entity");
factory.setDataSource(dataSource());
factory.afterPropertiesSet();
return factory.getObject();
}
#Bean
public EntityManager entityManager(EntityManagerFactory entityManagerFactory) {
return entityManagerFactory.createEntityManager();
}
#Bean
public PlatformTransactionManager transactionManager() throws SQLException {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
#Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
}
#Configuration
#Profile({"test"})
#EnableTransactionManagement(proxyTargetClass = true)
#EnableJpaRepositories(basePackages = { "com.jle.athleges.model.repository", "com.jle.athleges.security.repository" })
#ComponentScan(basePackages = { "com.jle.athleges.model.services", "com.jle.athleges.security.services" })
public class JpaConfigurationTest {
#Bean
public DataSource dataSource() throws SQLException {
System.out.println("use test");
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
builder.setName("test");
return builder.setType(EmbeddedDatabaseType.H2).build();
}
#Bean
public EntityManagerFactory entityManagerFactory() throws SQLException {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.jle.athleges.model.entity", "com.jle.athleges.security.entity");
factory.setDataSource(dataSource());
factory.afterPropertiesSet();
return factory.getObject();
}
#Bean
public EntityManager entityManager(EntityManagerFactory entityManagerFactory) {
return entityManagerFactory.createEntityManager();
}
#Bean
public PlatformTransactionManager transactionManager() throws SQLException {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
#Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
}
In my pom.xml, I have this :
<project>
…
<dependencies>
…
</dependencies>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
</profile>
</profiles>
<build>
<finalName>AthleGes</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<debug>true</debug>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty-maven-plugin.version}</version>
<configuration>
<jettyEnvXml>src/test/resources/jetty-env.xml</jettyEnvXml>
<scanIntervalSeconds>10</scanIntervalSeconds>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
And finally, I have a test class :
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles(profiles = {"test","dev"})
#ContextConfiguration(classes = { JpaConfigurationTest.class, JpaConfiguration.class, SecurityConfig.class })
#TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
})
public class MemberServiceImpTest {
static Logger log = LoggerFactory.getLogger(MemberServiceImpTest.class);
#Autowired
private MemberService memberService;
#Autowired
private MemberRepository repository;
#Before
public void setUp(){
repository.deleteAll();
}
#Test
public void saveMember() {
log.debug("Start saveMember");
Member a = new Member();
a.setFirstname("aaa");
a.setLastname("hhh");
a.setId(0L);
Assert.assertNotNull(memberService.save(a));
log.debug("End saveMember");
}
#Test
public void getAllMembers() {
log.debug("Start getAllMember");
long sizeBefore = repository.count();
Member a = new Member();
a.setFirstname("aaa");
a.setLastname("hhh");
a.setId(2L);
Member b = new Member();
b.setFirstname("aaa");
b.setLastname("hhh");
b.setId(1L);
memberService.save(a);
memberService.save(b);
Assert.assertEquals(memberService.getAll().size(),sizeBefore + 2);
log.debug("End getAllMember");
}
}
When I run my unit test from Eclipse, it is working fine. If I move the profile in the test class from dev to test and from test to dev, it is working. I mean the test pass and the displayed message "use dev" or "use test" is displayed.
I want to run the tests from maven (with m2e) and I created this configuration :
But when I change the profile, test is always started.
I tried to activate profile from Maven -> Select Maven Profile but I have been the same result.
I miss something but I don't know what. I don't understand.
Could you help me?
Thanks
As per your configuration #ActiveProfiles, both the profiles will be activated during your test execution. If you want to control the active spring profile for test cases through maven, then I would suggest you to remove #ActiveProfiles annotation from your test class and specify spring.profiles.active as a system property. You could do it using either of the following ways:
Set it in the maven surefire plugin configurtion:
<project>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
<profiles>
<profile>
<id>dev</id>
<activation>
<property>
<name>spring.profiles.active</name>
<value>dev</value>
</property>
</activation>
</profile>
<profile>
<id>test</id>
<activation>
<property>
<name>spring.profiles.active</name>
<value>test</value>
</property>
</activation>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dspring.profiles.active=${spring.profiles.active}</argLine>
</configuration>
</plugin>
</plugins>
</build>
</project>
You can simply run maven test as you are doing already by passing spring.profiles.active parameter without the profile name. Profile will be activated automatically using value of the property spring.profiles.active
OR
Pass it to surefire plugin through maven parameter during execution like:
mvn -DargLine="-Dspring.profiles.active=dev"
If you are running with different profiles regularly for testing purposes on Eclipse, you can select the active profile directly in Eclipse without modifying the pom.
Select active profile under Maven > Select Maven Profiles...
How to configure PropertySourcesPlaceholderConfigurer with custom .properties files for different environments (production, dev, staging)? on deploy spring throws "Could not resolve placeholder 'property.placeholder' in string value "classpath:${property.placeholder}" "
here is my pom.xml
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<property.placeholder>_developer.properties</property.placeholder>
</properties>
</profile>
<profile>
<id>staging</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<property.placeholder>_staging.properties</property.placeholder>
</properties>
</profile>
<profile>
<id>production</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<property.placeholder>_production.properties</property.placeholder>
</properties>
</profile>
</profiles>
here is PropertySourcesPlaceholderConfigurer configuration
static #Bean
public PropertySourcesPlaceholderConfigurer myPropertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer p = new PropertySourcesPlaceholderConfigurer();
org.springframework.core.io.Resource[] resourceLocations = new org.springframework.core.io.Resource[] {
new ClassPathResource("${property.placeholder}")
};
p.setLocations(resourceLocations);
return p;
}
it works in xml spring configuration but didn't work if I use java config. Have any idea how make it works?
I found another way to do what i want:
At first I add this plugin to builds section in my pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<id>1</id>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>src/main/resources/${property.placeholder}</file>
</files>
</configuration>
</execution>
<execution>
<id>2</id>
<phase>generate-resources</phase>
<goals>
<goal>write-project-properties</goal>
</goals>
<configuration>
<outputFile>
${project.build.outputDirectory}/application.properties
</outputFile>
</configuration>
</execution>
</executions>
</plugin>
At second I modify PropertySourcesPlaceholder configuration in my spring config file:
static #Bean
public PropertySourcesPlaceholderConfigurer myPropertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer p
= new PropertySourcesPlaceholderConfigurer();
org.springframework.core.io.Resource[] resourceLocations
= new org.springframework.core.io.Resource[] {
new ClassPathResource("application.properties")
};
p.setLocations(resourceLocations);
return p;
}
And also I add this annotation to my spring config class:
#PropertySource("classpath:application.properties")
So now I write env-dependent properties to different properties files (like "_developer.properties" or "_staging.properties") and when I build project with maven it has been copied to "application.properties", which I use in PropertySourcesPlaceholder configuration
Use System.getProperty() to get the environment variable.
Sample code:
Environment env = new Environment(new ClassResourceLocator(ClassUtils.getDefaultClassLoader()), System.getProperty("env"));
Create PropertySourcesPlaceholderConfigurer Bean:
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer()
{
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setPropertySources(new MyPropertySources());
return propertySourcesPlaceholderConfigurer;
}
MyPropertySources.java
public class MyPropertySources implements PropertySources{
private List<PropertySource<?>> sources = new ArrayList<>();
public EnvironmentPropertySources()
{
Environment env = new Environment(new ClassResourceLocator(ClassUtils.getDefaultClassLoader()), System.getProperty("env"));
PropertySource<?> source = ...;
// create class that extends PropertySource<String> and get property values from Environment
sources.add(source);
}
#Override
public Iterator<PropertySource<?>> iterator() {
return sources.iterator();
}
#Override
public boolean contains(String name) {
return true;
}
#Override
public PropertySource<?> get(String name) {
return sources.get(0);
}
}