Spring Boot Security and H2 console

The configuration shown below should be used only in a development environment and not in production.

After enabling Spring Security in your Spring Boot application, you will not be able to access the H2 database console anymore.

With its default settings under Spring Boot, Spring Security will block access to the H2 database console.

To be able to access the H2 database console under Spring Security you need to change these four things:

  • Enable h2 console in your application.properties file
spring.h2.console.enabled=true
  • Allow all access to the URL path /console/*.
httpSecurity.authorizeRequests().antMatchers("/").permitAll().and()
.authorizeRequests().antMatchers("/console/**").permitAll();
  • Disable CRSF (Cross-Site Request Forgery). By default, Spring Security will protect against CRSF attacks.
httpSecurity.csrf().disable();
  • Since the H2 database console runs inside a frame, you need to disable this in Spring Security.
httpSecurity.headers().frameOptions().disable();

So, the very, very simple security configuration that allows you to access h2-console should look like:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

        httpSecurity.authorizeRequests().antMatchers("/").permitAll().and()
                .authorizeRequests().antMatchers("/console/**").permitAll();

        httpSecurity.csrf().disable();
        httpSecurity.headers().frameOptions().disable();
    }
}

After applying these changes and trying to access your h2-console

http://localhost:8080/h2-console/

You should see the h2-console login page:

Simple Jersey example with Intellij IDEA Ultimate and Tomcat

Jersey

RESTful Web Services in Java.

Jersey is a reference implementation of the JAX-RS 2.0 API. Jersey provides it’s own API that extends the JAX-RS toolkit with additional features and utilities to further simplify RESTful service and client development.

In this example I will be using:

  • IntelliJ Idea Ultimate 2016.2
  • Jersey 2.23.2 (latest stable release of Jersey as of time of writing)
  • JDK 8
  • Tomcat 8.0.35

Create new project

To create a new project, open up the New Project dialog in IntelliJ. In the left menu, select Java Enterprise. To the right, select Web Application and ensure that Create web.xml is checked.

newproject

 

Add Maven support

To add Maven to your project, right-click on your project’s name in the Project sidebar and select Add Framework Support.

In the Add Frameworks Support, select Maven.

Once this is done, the pom.xml file will open in the editor. You will need to enter at least a groupId, usually your package name. At this point, it is helpful to enable auto-importing for library dependencies.

maven

Add Jersey dependencies to the Maven pom.xml file

<?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.programmerscuriosity</groupId>
    <artifactId>SimpleJersey</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>${jersey.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
        </dependency>
    </dependencies>

    <properties>
        <jersey.version>2.23.2</jersey.version>
    </properties>
    
</project>

 

Create a Resource

Inside of the src/main/java directory, create a new package matching your groupId.

And then create a simple java class – MyResource in my case.

package com.programmerscuriosity;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 * Created by marom on 27/09/16.
 */
@Path("myresource")
public class MyResource {

    /**
     * Method handling HTTP GET requests. The returned object will be sent
     * to the client as "text/plain" media type.
     *
     * @return String that will be returned as a text/plain response.
     */
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getIt() {
        return "Got it!";
    }
}

Modify index.jsp file by adding a link to the Jersey resource

<html>
  <head>
    <title>Simple Jersey</title>
  </head>
  <body>
  <p><a href="rest/myresource">Jersey resource</a>
  </body>
</html>

 

Check if Tomcat is configured properly.

tomcat-configuration

tomcat-deployment

 

Configure your servlet

Modify your web.xml file

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.programmerscuriosity</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

 

Before we run our application, first we need to add Jersey jars to the /WEB-INF/lib directory

add-artifacts

After selecting all jars right click and choose “Put into /WEB-INF/lib

Run your Application

jersey-resource
got-it

 

DONE!

 

 

Git for an absolute beginners

Before I started using Git on my personal and then on commercial projects, I was using for many years  Subversion – svn in short. SVN is still very popular but Git earned its strong position as well by being used in large and small projects for more than 10 years already.

Installing Git

The official website of Git has detailed information about installing on Linux, Mac, or Windows. In this case, I will be using Ubuntu 16.04 for demonstration purposes, and installing git in Linux (Ubuntu) is simple as typing:

marom@marom-E7440:~$ sudo apt-get install git

Before we dive into configuration and will start using Git a bit of terminology introduction is necessary.

Here’s the git terminology:

  • master – the repository’s main branch. Depending on the workflow it is the one people work on or the one where the integration happens
  • clone – copies an existing git repository, normally from some remote location to your local environment.
  • commit – submitting files to the repository (the local one); in other VCS it is often referred to as “checkin”
  • fetch or pull – is like “update” or “get latest” in other VCS. The difference between fetch and pull is that pull combines both, fetching the latest code from a remote repo as well as performs the merging.
  • push – is used to submit the code to a remote repository
  • remote – these are “remote” locations of your repository, normally on some central server.
  • SHA – every commit or node in the Git tree is identified by a unique SHA key. You can use them in various commands in order to manipulate a specific node.
  • head – is a reference to the node to which our working space of the repository currently points.
  • branch – is just like in other VCS with the difference that a branch in Git is actually nothing more special than a particular label on a given node. It is not a physical copy of the files as in other popular VCS.

Initial Configuration

We need to configure our name and email. You can do it as follows, replacing the values with your own name and email.

marom@marom-E7440:~$ git config --global user.name "Courious Programmer"
marom@marom-E7440:~$ git config --global user.email "blog@programmerscuriosity.com"

It is important to note that if you do not set your name and email, certain default values will be used.

Create a new Git Repository

Before starting, let’s create a new directory where the git repository will be created and ‘move’ into it.

marom@marom-E7440:~/SmallProjects$ mkdir blogGitIntroduction
marom@marom-E7440:~/SmallProjects$ cd blogGitIntroduction/
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ 

Now we can initialize our first git repository.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git init
Initialized empty Git repository in /home/marom/SmallProjects/blogGitIntroduction/.git/

To check the status of our repository git status command can be used.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git status
On branch master

Initial commit

nothing to commit (create/copy files and use "git add" to track)

Create and commit a new file

The next step is to create a new file and add some content to it.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ touch blogpost.txt

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ echo "Hello, Git World!" > blogpost.txt

Let’s check what happen in our git repository.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	blogpost.txt

nothing added to commit but untracked files present (use "git add" to track)

To “register” the file for committing we need to add it to git using:

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git add blogpost.txt 

And again, let’s check what happen in our git repository.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git add secondFile.txt 
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git commit -m "add second file to the project"
[master 763b757] add second file to the project
 1 file changed, 1 insertion(+)
 create mode 100644 secondFile.txt

 

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   blogpost.txt

We can now commit it to the repository.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git commit -m "add first file to the project"
[master (root-commit) 55db76b] add first file to the project
 1 file changed, 1 insertion(+)
 create mode 100644 blogpost.txt

Let’s add another file to the project.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ echo "this is text from second file in project" > secondFile.txt
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git add secondFile.txt 
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git commit -m "add second file to the project"
[master 763b757] add second file to the project
 1 file changed, 1 insertion(+)
 create mode 100644 secondFile.txt

 

Create a (feature) branch

Branching and merging is what makes Git so powerful and for what it has been optimised, being a distributed version control system (VCS). Indeed, feature branches are quite popular to be used with Git. Feature branches are created for every new kind of functionality you’re going to add to your system and they have usually deleted afterwards once the feature is merged back into the main integration branch (normally the master branch). The advantage is that you can experiment with new functionality in a separate, isolated “playground” and quickly switch back and forth to the original “master” branch when needed. Moreover, it can be easily discarded again (in case it is not needed) by simply dropping the feature branch. But let’s get started and create the new feature branch:

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git branch new-feature-branch

To see a list of all branches we need to use git branch command.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git branch
* master
  new-feature-branch

A star next to master branch indicates that this is a current branch.

Let’s switch to this newly created branch and modify one of the files.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git checkout new-feature-branch 
Switched to branch 'new-feature-branch'
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git branch
  master
* new-feature-branch
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ echo "Let's modify file in the branch" >> blogpost.txt
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ cat blogpost.txt 
Hello, Git World!
Let's modify file in the branch

And then add and commit it to the branch.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git add blogpost.txt 
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git commit -m "modify file on the branch"
[new-feature-branch 3a30916] modify file on the branch
 1 file changed, 1 insertion(+)

 

Ok, it’s time to complicate it and cause some conflicts. To do this we need to switch to ‘master’ branch and modify the blogpost.txt file.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git checkout master
Switched to branch 'master'
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git branch
* master
  new-feature-branch
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ echo "This change was done on master branch" >> blogpost.txt
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ cat blogpost.txt 
Hello, Git World!
This change was done on master branch

 

If you need to commit a file that was already added to the git repository you can use command ‘commit -a -m’

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git commit -a -m "change blogpost file"
[master 1a139b5] change blogpost file
 1 file changed, 1 insertion(+)

Merge and resolve conflicts

The next step would be to merge our feature branch back into ‘master’. This is done by using the merge command.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git merge new-feature-branch 
Auto-merging blogpost.txt
CONFLICT (content): Merge conflict in blogpost.txt
Automatic merge failed; fix conflicts and then commit the result.
marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ cat blogpost.txt 
Hello, Git World!
<<<<<<< HEAD
This change was done on master branch
=======
Let's modify file in the branch
>>>>>>> new-feature-branch

Edit file and resolve conflict and commit changes to the branch.

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ cat blogpost.txt 
Hello, Git World!

This change was done on master branch

Let's modify file in the branch

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git commit -a -m "resolve merge conflict"
[master 7e2abc0] resolve merge conflict

 

Rollback

What if we want to undo everything back to the state before the commit?

First, we need to get SHA identifiers (unique ‘id’ for each node in git tree).

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git log
commit 4afb2d5caf73f48be16cc78875b8fe58c72ce4dd
Author: Courious Programmer <blog@programmerscuriosity.com>
Date:   Sun Sep 11 10:02:16 2016 +0200

    prepare for rollback

commit 7e2abc0dc4f56672bf0f209551698c942dbc7071
Merge: 1a139b5 3a30916
Author: Courious Programmer <blog@programmerscuriosity.com>
Date:   Sun Sep 11 09:57:50 2016 +0200

    resolve merge conflict

commit 1a139b5dd7a9f42e4f7f570081b65dbc4d27529b
Author: Courious Programmer <blog@programmerscuriosity.com>
Date:   Sun Sep 11 09:37:40 2016 +0200

    change blogpost file

commit 3a309165db700a00fbe1a0f2451700c59532d629
Author: Courious Programmer <blog@programmerscuriosity.com>
Date:   Sun Sep 11 09:26:56 2016 +0200

 

and then move back in time to the desired node/commit

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git reset --hard 7e2abc0
HEAD is now at 7e2abc0 resolve merge conflict

 

marom@marom-E7440:~/SmallProjects/blogGitIntroduction$ git log
commit 7e2abc0dc4f56672bf0f209551698c942dbc7071
Merge: 1a139b5 3a30916
Author: Courious Programmer <blog@programmerscuriosity.com>
Date:   Sun Sep 11 09:57:50 2016 +0200

    resolve merge conflict

commit 1a139b5dd7a9f42e4f7f570081b65dbc4d27529b
Author: Courious Programmer <blog@programmerscuriosity.com>
Date:   Sun Sep 11 09:37:40 2016 +0200

    change blogpost file

commit 3a309165db700a00fbe1a0f2451700c59532d629
Author: Courious Programmer <blog@programmerscuriosity.com>
Date:   Sun Sep 11 09:26:56 2016 +0200

    modify file on the branch

commit 763b75761c9d95a68d1d1e56bd4d2b0390c03379
Author: Courious Programmer <blog@programmerscuriosity.com>
Date:   Sat Sep 10 19:13:28 2016 +0200

 

And that’s it. It is everything that is needed to start using git. I have covered here only simple commands. For more advanced commands and explanations I highly recommend reading this book: Pro GIT.

Spring – Conditional annotation

Spring 4 has introduced a new annotation @Conditional. It is used to develop an “If-Then-Else” type of conditional checking for bean registration. Let us see how we can use @Conditional annotation to check a property value is dev or prod from environment. For learning we will use Java based configurations in this example.

Create Project Domain class with id, name and duration properties with getters only as shown below.

public class Project {

    private int id;
    private String name;
    private double duration;

    public Project(int id, String name, double duration) {
        this.id = id;
        this.name = name;
        this.duration = duration;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public double getDuration() {
        return duration;
    }
}

Create Utility classes to represent in-memory Databases. For simplicity, we are not interacting with Databases. DevDatabaseUtil class represents DEV database and ProductionDatabaseUtil class represents PROD database with some data.

public interface DataSource {

    List<Project> getProjectsList();
}
public class DevDatabaseUtil implements DataSource {

    @Override
    public List<Project> getProjectsList() {

        List<Project> projects = new ArrayList<>();
        Project projectWeb = new Project(1, "Web page for Qwerty", 160);
        Project projectWeb2 = new Project(2, "Web page for Asdfgh", 40);
        Project projectWeb3 = new Project(3, "Fix web page for Dfrtghy", 45.50);

        projects.add(projectWeb);
        projects.add(projectWeb2);
        projects.add(projectWeb3);

        return projects;
    }
}
public class ProductionDatabaseUtil implements DataSource {

    @Override
    public List<Project> getProjectsList() {

        List<Project> projects = new ArrayList<>();
        Project projectWeb = new Project(100, "Web page for Client 1", 230);
        Project projectWeb2 = new Project(200, "Web page for Client 2", 35);


        projects.add(projectWeb);
        projects.add(projectWeb2);

        return projects;
    }
}

Create a ProjectDAO class to represent DAO Layer.

public class ProjectService {

    private ProjectDAO projectDAO;

    public ProjectService(ProjectDAO projectDAO) {
        this.projectDAO = projectDAO;
    }

    public List<Project> getProjects() {
        return projectDAO.getProjects();
    }
}

Now it’s time to implement Conditional checking by using@Conditional annotation. Both condition checking classes implements Spring’s Condition interface matches() method. Both Conditional classes checks for “database.name” from environment. If this values is “dev”, then DevDataSourceCondition’s matches() method returns true. Otherwise false. In the same way, if this property value is “prod”, then ProdDataSourceCondition’s matches() method returns true. Otherwise false.

public class DevDataSourceCondition implements Condition {

    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String dbname = conditionContext.getEnvironment().getProperty("database.name");
        return dbname.equalsIgnoreCase("dev");
    }
}
public class ProductionDataSourceCondition implements Condition {

    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {

        String dbname = conditionContext.getEnvironment().getProperty("database.name");
        return dbname.equalsIgnoreCase("prod");
    }
}

Create Spring’s Java-based configuration classes

@Configuration
public class ProjectConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public ProjectService projectService() {
        return new ProjectService(projectDAO());
    }

    @Bean
    public ProjectDAO projectDAO() {
        System.out.println("ProjectDAO projectDAO()" + dataSource);
        return new ProjectDAO(dataSource);
    }
}
@Configuration
public class ProjectDataSourceConfig {

    @Bean(name="dataSource")
    @Conditional(value=DevDataSourceCondition.class)
    public DataSource getDevDataSource() {
        return new DevDatabaseUtil();
    }

    @Bean(name="dataSource")
    @Conditional(ProductionDataSourceCondition.class)
    public DataSource getProdDataSource() {
        return new ProductionDatabaseUtil();
    }

}

Now it’s time to write JUnits to test Spring’s @Conditional classes.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringForBlogDemoApplication.class)
public class ProdConditionalTest {

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void testProdDataSource() {
        ProjectService service = (ProjectService) applicationContext.getBean("projectService");
        assertNotNull(service);
        List<Project> projects = service.getProjects();
        assertEquals(2, projects.size());
        assertEquals("Web page for Client 1", projects.get(0).getName());
        assertEquals("Web page for Client 2", projects.get(1).getName());
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringForBlogDemoApplication.class)
public class DevConditionalTest {

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void testDevDataSource() {
        ProjectService service = (ProjectService) applicationContext.getBean("projectService");
        assertNotNull(service);
        List<Project> projects = service.getProjects();
        assertEquals(3, projects.size());
        assertEquals("Web page for Qwerty", projects.get(0).getName());
        assertEquals("Web page for Asdfgh", projects.get(1).getName());
        assertEquals("Fix web page for Dfrtghy", projects.get(2).getName());
    }
}

 

Spring Profiles

A Spring application can be configured to behave differently in different environments using different profiles. For example, you can register beans based on what kind of database you’re running (development, production, test).

You can then configure a deployment to run using zero or more profiles, by providing a spring.profiles.active property. For example, to run the application using production and dev profile, add the following line in application.properties:

spring.profiles.active: dev

To test it, let’s create two classes responsible for database datasource setup and then run our application with datasource configuration setup based on active profile.

@Component
@Profile("dev")
public class DevDatasourceConfig implements DatasourceConfig {

    @Override
    public void setup() {
        System.out.println("Datasource config based on development profile");
    }
}
@Component
@Profile("production")
public class ProductionDatasourceConfig implements DatasourceConfig {

    @Override
    public void setup() {
        System.out.println("Datasource config based on production profile");
    }
}

To inject our DatasourceConfig interface; depending on the active profile we need to create a ‘test’ class. Spring will injects DevDatasourceConfig or ProductionDatasourceConfig bean:

@RestController
public class DatasourceProfileController {

    @Autowired
    DatasourceConfig datasourceConfig;

    @RequestMapping("/profiles")
    public String profiles() {
        datasourceConfig.setup();
        return "Database setup based on Spring profile configuration";
    }
}

When the “dev” profile is active spring injects DevDatasourceConfig object, and on call of setup() method following is the output:

Datasource config based on development profile

To see a list of active profiles you just need to inject Environment and then iterate through a list of active profiles.

@RestController
public class DatasourceProfileController {

    @Autowired
    DatasourceConfig datasourceConfig;

    @Autowired
    Environment environment;

    @RequestMapping("/profiles")
    public String profiles() {
        datasourceConfig.setup();

        for (final String profileName : environment.getActiveProfiles()) {
            System.out.println("Currently active profile - " + profileName);
        }
        
        return "Database setup based on Spring profile configuration";
    }
}
When you’ll run our app, tou should get a list of active profiles:
Datasource config based on development profile
Currently active profile - dev

Any bean that does not specify a profile belongs to “default” profile.

Spring also provides a way to set the default profile when no other profile is active – by using the “spring.profiles.default” property.

For testing purposes, to specify what profile is active you need to specify an active profile by using @ActiveProfiles annotation:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { SpringForBlogDemoApplication.class })
@ActiveProfiles("dev")
public class DatasourceProfileControllerTest {

    @Autowired
    DatasourceConfig datasourceConfig;

    @Test
    public void test_datasourceSetupBasedOnProfile() {
        datasourceConfig.setup();
    }
}

The profile names can also be passed in via a JVM system parameter. The profile names passed as the parameter will be activated during application start-up:

-Dspring.profiles.active=dev

DI – Configuring Beans

Component annotations

Spring creates beans for classes with auto component scanning features by using @Component. @Component annotation is not only one you can use for creating beans, there are others more ‘specialized’ annotations.

  • @Controller – Indicates a controller component in the presentation layer
  • @Service – Indicates a Service component in the business layer
  • @Repository – Indicates DAO component in the persistence layer

So, which one to use? It’s really doesn’t matter. Take a look at the source code one of those annotations:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    String value() default "";
}

You will notice that all @Repository,@Service or @Controller are annotated with @Component. So, can we use just @Component for all the components for auto scanning? Yes, you can, and Spring will auto scan all your components with @Component annotated.

It’s working fine, but not a good practice, for readability, you should always declare @Repository,@Service or @Controller for a specified layer to make your code more easier to read.

Configuration classes

Let’s assume that our Service classes (SmsService, TweetService, MailService) are part of some third party JAR and we won’t be able to annotate those with @Component. In this case we can use Java configuration classes. To make our application working again we need to create some config class where we will add our service classes to be able to be scanned by Spring.

@Configuration
public class MessageConfig {

    @Bean
    public MessageService emailService() {
        return new EmailService();
    }

    @Bean
    public MessageService smsService() {
        return new SmsService();
    }

    @Bean
    public MessageService tweetService() {
        return new TweetService();
    }
}

Annotating a class with the @Configuration indicates that the class can be used by the Spring IoC container as a source of bean definitions. The @Bean annotation tells Spring that a method annotated with @Bean will return an object that should be registered as a bean in the Spring application context. The name of the methods become the names
of the beans by default.

DI – Two beans implementing same inteface

How to inject the right one?

To see what happens lets annotate with @Component our TweetService class.

@Component
public class TweetService implements MessageService {


    public void sendMessage(String subject, String message) {
        System.out.println("Tweet: " + subject + " - " + message);
    }
}

Trying to run the application you’ll get an error:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.programmerscuriosity.springforblogdemo.di.example.four.MessageService] is defined: expected single matching bean but found 2: smsService,tweetService

Spring, when trying to find a suitable bean for injecting to the messageService variable, finds two beans – the instances of both TweetService and SmsService.

Let’s try to fix it. One of few ways to do it is, to specify a name in @Resource annotation.

@RestController
public class MessageController {

    @Resource(name = "tweetService")
    private MessageService messageService;

    @RequestMapping("/message")
    public String sendMessage() {
        messageService.sendMessage("Very important:", "Please read this carefully.");
        return "Your message was sent";
    }
}

Spring will then be able to inject the exact bean without any error.

Another alternative will be to give a name to the bean to match the resource name.

@RestController
public class MessageController {

    @Resource
    private MessageService messageService;

    @RequestMapping("/message")
    public String sendMessage() {
        messageService.sendMessage("Very important:", "Please read this carefully.");
        return "Your message was sent";
    }
}
@Component("messageService")
public class SmsService implements MessageService {

    @Override
    public void sendMessage(String subject, String message) {
        System.out.println("SMS: " + subject + " - " + message);
    }
}

Yet another option to tell Spring which bean to inject is to use @Primary annotation.

@Primary
@Component
public class TweetService implements MessageService {


    public void sendMessage(String subject, String message) {
        System.out.println("Tweet: " + subject + " - " + message);
    }
}
@Component
public class SmsService implements MessageService {

    @Override
    public void sendMessage(String subject, String message) {
        System.out.println("SMS: " + subject + " - " + message);
    }
}

The application should still run fine.

A more powerful (it not only works on setters, but on any method, including the constructors) but still very similar to @Resource is @Autowired annotation.

@RestController
public class MessageController {


    private MessageService messageService;

    @Autowired
    public MessageController(MessageService messageService) {
        this.messageService = messageService;
    }

    @RequestMapping("/message")
    public String sendMessage() {
        messageService.sendMessage("Very important:", "Please read this carefully.");
        return "Your message was sent";
    }
}

However, @Autowired does not take the name element. Instead, we need to use @Qualifier along with @Autowired.

@RestController
public class MessageController {


    private MessageService messageService;

    @Autowired
    public MessageController(@Qualifier("sms") MessageService messageService) {
        this.messageService = messageService;
    }

    @RequestMapping("/message")
    public String sendMessage() {
        messageService.sendMessage("Very important:", "Please read this carefully.");
        return "Your message was sent";
    }
}
@Component
@Qualifier("sms")
public class SmsService implements MessageService {

    @Override
    public void sendMessage(String subject, String message) {
        System.out.println("SMS: " + subject + " - " + message);
    }
}

By default, the qualifier of a bean will be same as its name.

@RestController
public class MessageController {


    private MessageService messageService;

    @Autowired
    public MessageController(@Qualifier("tweetService") MessageService messageService) {
        this.messageService = messageService;
    }

    @RequestMapping("/message")
    public String sendMessage() {
        messageService.sendMessage("Very important:", "Please read this carefully.");
        return "Your message was sent";
    }
}
@Component
public class TweetService implements MessageService {


    public void sendMessage(String subject, String message) {
        System.out.println("Tweet: " + subject + " - " + message);
    }
}

 

Spring also has @Inject , which is synonymous to @Autowired. It’s part of the Java CDI JSR-300 standard, and so Spring thought to support it. What is the difference between @Inject and @Autowired?

The short answer: There is no different and can be used interchangeably.

In more detail @Inject is part of the Java CDI (Contexts and Dependency Injection) standard introduced in Java EE 6 (JSR-300). Spring has chosen to support using @Inject synonymously with their own @Autowired annotation.@Autowired is Spring’s own annotation. In a Spring application, the two annotations works the same way as Spring has decided to support some JSR-300 annotations in addition to their own.

 

DI – Dependency injection by name and type

@Resource by default the name of the bean will be its class name in camelCase. That means, the SmsService instance, which will be put in the application context as a result of being annotated with @Component, will be named as smsService. To change the default name, we can supply a value element to @Component:

@Component(value = "sms")
public class SmsService implements MessageService {

    @Override
    public void sendMessage(String subject, String message) {
        System.out.println("SMS: " + subject + " - " + message);
    }
}
@RestController
public class MessageController {

    @Resource(name = "sms")
    private MessageService messageService;

    @RequestMapping("/message")
    public String sendMessage() {
        messageService.sendMessage("Very important:", "Please read this carefully.");
        return "Your message was sent";
    }
}

This behavior is called dependency injection by name.

Now I show you an example of DI by name:

But, if we remove a name parameter from @Resource annotation and then we’ll try to run our example, everything should work as before. Why?

@RestController
public class MessageController {

    @Resource
    private MessageService messageService;

    @RequestMapping("/message")
    public String sendMessage() {
        messageService.sendMessage("Very important:", "Please read this carefully.");
        return "Your message was sent";
    }
}
@Component
public class SmsService implements MessageService {

    @Override
    public void sendMessage(String subject, String message) {
        System.out.println("SMS: " + subject + " - " + message);
    }
}

At the start of application Spring first try to find a bean with messageService name and will fail, next step will be to try to find a bean of the same type, and in our example as SmsService is a subtype of MessageService and as a result of successfully running application, we should get:

Your message was sent

And in the console log:

2016-04-27 10:51:11.006 INFO 9854 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2016-04-27 10:51:11.029 INFO 9854 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 23 ms
SMS: Very important: - Please read this carefully.

 

Hello, Programmer’s curiosity

An example of very simple Spring application that will be extended in next posts to demonstrate Spring framework and DI (dependency injection).

For all examples I’ll be using IntelliJ Idea Ultimate, an ide of my choice for at last 3 years, I love it’s features and productivity speedup that comes with it.

Creating a new Spring project

There are many ways to create a new Spring project. You can create it from scratch or use Spring Initializr plugin for IntelliJ Idea or do it via web Spring Initializr (it creates a zip file, which you can download, unzip and import in your IDE).

SpringInitializr

Next step is to enter few metadata for our project:

Name
It’s the name of the project, e.g. spring-for-blog-demo
Type
It’s the build tool selection to help us compile and package our project. There are a couple of options: Maven and Gradle. I prefer to go with Maven, because of its wide adoption, unless there is a specific need for Gradle.
Packaging
You’ll find two options here – JAR and WAR.
The executable of our application. That JAR or WAR can run standalone, with the standard java -jar command.
Choose JAR packaging here, unless you are using JSP, which needs WAR packaging.
Java version
Our choice is 1.8 here.
Group and Artifact
Group and Artifact uniquely identify a project. Group will identify your project uniquely across all projects, what means that has to be at least as a domain name you control (no problem if you don’t own a domain – just use some name which you feel will be unique), and you can create as many subgroups as you want, e.g. com.programmerscuriosityArtifact uniquely identifies the project inside the group. It is the name of the jar without version. You can choose whatever name you want with lowercase letters and no strange symbols e.g. springforblogdemo.
Version
If you distribute it then you can choose any typical version with numbers and dots (1.0, 1.1, 1.0.1, …). Don’t use dates as they are usually associated with SNAPSHOT (nightly) builds. For our purpose just leave it untouched.
Description
This is a one line description of the project.
Package
This will be the name of the root package of your application. The common practice for naming it is to join the group and the artifact in some way, e.g. com.programmerscuriosity.springblogdemo.
Remember that “-” isn’t allowed here.

NewProject_metadata

Boot version
This is the version of Spring Boot to use. Normally we’d choose the latest stable release.
Dependencies
This section asks us to choose the dependencies needed. Whatever we choose here will go into the configuration file of the build tool. The build tool will then automatically fetch the needed JARs and put those in the classpath. So, choose just Web for now, and more dependencies can easily be added into the configuration file later.

NewProject_dependencies

Press Next and Finish to create the project in your workspace.

NewProject_structure_and_pom

Running our application at this stage won’t show any results apart from getting an error page (not even defined by us).

WhiteLabelPage

So, lets create a simple controller class and try to display at least simple Hello message.

Create a new package, e.g. com.programmerscuriosity.springforblogdemo.controllers. Inside that package, create a new class, HelloController:

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
        return "Hello, Programmer's curiosity blog";
    }
}

Start your server and type http://localhost:8080/hello in your browser.

hello_programmers_curiosity

And that’s it. We’ve got our base project for further posts about Spring DI ready and running.

 

Spring Framework Modules

spring-overview

The Spring Framework provides about 20 modules which can be used based on an application requirement.

Core Container:

The Core Container consists of the Core, Beans, Context, and Expression Language modules whose detail is as follows:

  • The Core module provides the fundamental parts of the framework, including the IoC and Dependency Injection features.
  • The Bean module provides BeanFactory which is a sophisticated implementation of the factory pattern.
  • The Context module builds on the solid base provided by the Core and Beans modules and it is a medium to access any objects defined and configured. The ApplicationContext interface is the focal point of the Context module.
  • The SpEL module provides a powerful expression language for querying and manipulating an object graph at runtime.

Data Access/Integration:

The Data Access/Integration layer consists of the JDBC, ORM, OXM, JMS and Transaction modules whose detail is as follows:

  • The JDBC module provides a JDBC-abstraction layer that removes the need to do tedious JDBC related coding.
  • The ORM module provides integration layers for popular object-relational mapping APIs, including JPA, JDO, Hibernate, and iBatis.
  • The OXM module provides an abstraction layer that supports Object/XML mapping implementations for JAXB, Castor, XMLBeans, JiBX and XStream.
  • The Java Messaging Service JMS module contains features for producing and consuming messages.
  • The Transaction module supports programmatic and declarative transaction management for classes that implement special interfaces and for all your POJOs.

Web:

The Web layer consists of the Web, Web-MVC, Web-Socket, and Web-Portlet modules whose detail is as follows:

  • The Web module provides basic web-oriented integration features such as multipart file-upload functionality and the initialization of the IoC container using servlet listeners and a web-oriented application context.
  • The Web-MVC module contains Spring’s model-view-controller (MVC) implementation for web applications.
  • The Web-Socket module provides support for WebSocket-based, two-way communication between client and server in web applications.
  • The Web-Portlet module provides the MVC implementation to be used in a portlet environment and mirrors the functionality of Web-Servlet module.

Miscellaneous:

There are few other important modules like AOP, Aspects, Instrumentation, Web and Test modules whose detail is as follows:

  • The AOP module provides aspect-oriented programming implementation allowing you to define method-interceptors and pointcuts to cleanly decouple code that implements functionality that should be separated.
  • The Aspects module provides integration with AspectJ which is again a powerful and mature aspect oriented programming (AOP) framework.
  • The Instrumentation module provides class instrumentation support and class loader implementations to be used in certain application servers.
  • The Messaging module provides support for STOMP as the WebSocket sub-protocol to use in applications. It also supports an annotation programming model for routing and processing STOMP messages from WebSocket clients.
  • The Test module supports the testing of Spring components with JUnit or TestNG frameworks.