[Spring] Simple Example with @Value and annotation driven configuration (no xml)

This is an example of a simple maven Spring application run as a standalone application which demonstrates the use of properties files and annotation based configuration.

1. The Configuration Bean. Here are 2 important things:

  1. You need to provide basePackages to the package where your applicaiton resides. In particular, where you MainClass resides.
  2. You need to define the bean of type PropertySourcesPlaceholderConfigurer as shown below.
package com.vvirlan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
@Configuration
@ComponentScan(basePackages = "com.vvirlan")
public class AppConfig {

	/*
	 * PropertySourcesPlaceHolderConfigurer Bean only required for @Value("{}")
	 * annotations. Remove this bean if you are not using @Value annotations for
	 * injecting properties.
	 */
	@Bean
	public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
		return new PropertySourcesPlaceholderConfigurer();
	}
}

2. The Class which contains the properties you want to load with @Value. Here the important thing is to provide the path to the properties file (for maven it must be under src/main/resources).

package com.vvirlan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource(value = { "classpath:app.properties" })
public class TestMe {
	@Value("${me}")
	private String me;
		public String getMe() {
		return me;
	}
}

3. app.properties file itself (put under src/main/resources):

me=Vladimir

4. The MainClass. Here the important thing is to instantiate your MainClass in Spring fashion. If you do MainClass cl = new MainClass(); it just won’t work (the autowiring I mean). Don’t forget to close the context when you’re done.

package com.vvirlan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class MainClass {
	@Autowired
	private TestMe me;
	public static void main(String[] args) {
                AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		MainClass cl = context.getBean(MainClass.class);
		cl.start();
		context.close();
	}

	private void start() {
		System.out.println(me.getMe());
	}
}

5. pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.vvirlan</groupId>
  <artifactId>springexample</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <dependencies>

  <dependency>
  	<groupId>org.springframework</groupId>
  	<artifactId>spring-core</artifactId>
  	<version>4.1.5.RELEASE</version>
  </dependency>
  <dependency>
  	<groupId>org.springframework</groupId>
  	<artifactId>spring-beans</artifactId>
  	<version>4.1.5.RELEASE</version>
  </dependency>
  <dependency>
  	<groupId>org.springframework</groupId>
  	<artifactId>spring-context</artifactId>
  	<version>4.1.5.RELEASE</version>
  </dependency>
  </dependencies>
</project>

[SOLVED] Spring Security allow webjars through

So if you implemented Spring Security in your project, you might have problems with webjars not being allowed through. You need to set this configuration in your WebSecurityConfiguration:

 

@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().antMatchers("/webjars/**").permitAll();
		http.authorizeRequests().anyRequest().authenticated();
         http.formLogin()
         .loginPage("/login")
         .failureUrl("/login?error")
         .usernameParameter("email")
         .permitAll()
         .and()
         .logout()
         .logoutUrl("/logout")
         .deleteCookies("remember-me")
         .logoutSuccessUrl("/")
         .permitAll()
         .and()
         .rememberMe();
	}

 

[STARTER] Spring + AOP (Aspect Oriented Programming)

1. The Performance interface

package aop.concert;
public interface Performance {
	public void perform();
}

2. The actual Aspect

package aop.concert;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class Audience {
	@Before("execution(** aop.concert.Performance.perform(..))")
		public void silencePhones() {
			System.out.println("Silencing phones.");
		}
}

3. RockPerfomance

package aop.concert;
public class RockPerformance implements Performance {
	public RockPerformance() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public void perform() {
		System.out.println("ROCK PERFORMING");
	}
}

4. Beans Configuration

package aop.concert;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class AppConfig {
	@Bean(name = "performance")
	public Performance getPerformance() {
		return new RockPerformance();
	}
	@Bean
	public Audience audience() {
		return new Audience();
	}
}

5. Main class

package aop.concert;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainClass {
	@Autowired
	Performance rc;
	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Performance pe = (Performance)context.getBean("performance");
		pe.perform();
	}
}

6. pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.springframework.samples</groupId>
	<artifactId>aop</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>

		<!-- Generic properties -->
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Spring -->
		<spring-framework.version>4.1.7.RELEASE</spring-framework.version>

		<!-- Hibernate / JPA -->
		<hibernate.version>4.2.1.Final</hibernate.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

		<!-- Test -->
		<junit.version>4.11</junit.version>

	</properties>

	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>


		<!-- Test Artifacts -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring-framework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.6</version>
		</dependency>

	</dependencies>
</project>

7. Layout
Screenshot_2015-07-31_16-52-19

[Starter] Spring Runtime autowiring (Implicit bean discovery) – non boot

Here is a starter for a Spring 4 + Maven application that makes use of implicit bean discovery and loads some data from a properties file:

1. The bean. Make sure to:

  • create a default constructor.
  • add the @Component annotation denoting that it will be a bean
package com.vvirlan.spring.examples;
import org.springframework.stereotype.Component;

@Component
public class BlankDisc {
	private String name;
	private String title;

	public BlankDisc(){}

	public BlankDisc(String name, String title) {
		this.name = name;
		this.title = title;
	}
	
	public void play() {
		System.out.println("Name: "+name+" Title: "+title);
	}
}

2. Define the Configuration java class. Here make sure to:

  • Add the @Configuration annotation which says that this class will be used for bean configuration
  • @PropertySoource which says where to find you properties file
  • @ComponentScan saying that configuration is done by automatically scanning all the classes which have the @Component annotation
  • @Bean annotation marking this method as a bean (it will return a bean of the specified type.
package com.vvirlan.spring.examples;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

@Configuration
@PropertySource("classpath:app.properties")
@ComponentScan
public class ExpressiveConfig {

	@Autowired
	Environment env;
	@Bean
	public BlankDisc disc() {
		return new BlankDisc(env.getProperty("disc.title"),
				env.getProperty("disc.artist"));
	}
}

3. app.properties with the contents:

disc.title=The Title
disc.artist=The Name Artist

4. And a JUnit test. The important parts here:

  • @RunWith(SpringJUnit4ClassRunner.class)
  • @ContextConfiguration(classes=ExpressiveConfig.class) – specifies which class is used for bean configuration
import static org.junit.Assert.*;

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 com.vvirlan.spring.examples.BlankDisc;
import com.vvirlan.spring.examples.ExpressiveConfig;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=ExpressiveConfig.class)
public class TestDisc {
	@Autowired
	BlankDisc disc;
	
	@Test
	public void test() {
		disc.play();
	}
}

5. pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework.samples</groupId>
  <artifactId>RuntimeAutowiring</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <properties>
		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Spring -->
		<spring-framework.version>3.2.3.RELEASE</spring-framework.version>

		<!-- Hibernate / JPA -->
		<hibernate.version>4.2.1.Final</hibernate.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

		<!-- Test -->
		<junit.version>4.11</junit.version>

	</properties>
	
	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>
		
		<!-- Test Artifacts -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring-framework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
	</dependencies>	
</project>

6. Directory structure

Screenshot_2015-07-30_22-37-14