Yearly Archives: 2016


How to force Spring Boot Security to say a little bit more?

By default spring boot security isn’t too talkative.
If you struggle with some problems and want to see what is going on under the covers, you can always switch to wider log level.

You can do it by providing this property in your application.yml or application.properties file.

logging.level.org.springframework.security: DEBUG

Additionaly you can turn on Spring Web debug logs and set debug parameter to true in your @EnableWebSecurity annotation

logging.level.org.springframework.web: DEBUG
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {...}

How jsonpath can help you to test rest controllers?

Introduction

In this post, I will show how you can write assertions to json strings.
When I test my rest controllers, I want to check that responses bodies contains exactly the json that I assume.

Json path is a tool which can return you only the part of json that you want.
You give it a pattern to express which part of data you want to receive.

JsonPath patterns

I have the following json:

[
	{
		"name":"Lukas",
		"age":23
	},
	{
		"name":"Jack",
		"age":35
	},
	{
		"name":"Michael",
		"age":32
	}
]

When I use pattern:

$[0].name

I receive a string:
“Lukas”
When pattern will be:

$.[1].age

Result:
35

You can see that expressions are something like regexp for json.

Java tests examples

Ex.1
Lets assume that our controller should return json similar to this:

{
	“id”:12
}

when we request it by -> /user/12

@Test
public void shouldReturnUserWithId() throws Exception {
   String responseContent = mockMvc.perform(get("/user/" + USER_ID).accept(MediaType.APPLICATION_JSON_UTF8))
           .andExpect(status().isOk())
           .andReturn().getResponse().getContentAsString();

   Integer loginFromResponse = JsonPath.parse(responseContent).read("$.id");
   Assert.assertEquals(USER_ID, loginFromResponse.intValue());
}

Ex.2
We assume that json should be an object with array of objects with “id” property.

{
	[
{	
	“id”:1
},
{	
	“id”:2
},
{	
	“id”:3
}
	]
}
@Test
public void shouldReturnArrayOfUsers() throws Exception {
   String responseContent = mockMvc.perform(get("/user").accept(MediaType.APPLICATION_JSON_UTF8))
           .andExpect(status().isOk())
           .andReturn().getResponse().getContentAsString();

   List<integer> ids = JsonPath.parse(responseContent).read("$[*].id");
   MatcherAssert.assertThat(ids, Matchers.hasSize(3));
   MatcherAssert.assertThat(ids, Matchers.containsInAnyOrder(1,2,3));
}
</integer>

As you can see, we can use hamcrest mathers to test collection returned by jsonpath api.

Ex.3

@Test
public void shouldReturnsUsersWithListsOfPosts() throws Exception {
   String responseContent = mockMvc.perform(get("/user").accept(MediaType.APPLICATION_JSON_UTF8))
		   .andExpect(status().isOk())
		   .andReturn().getResponse().getContentAsString();

   List<string> postTitles = JsonPath.parse(responseContent).read("$[*].posts[0].title");
   MatcherAssert.assertThat(postTitles, Matchers.hasSize(3));
   MatcherAssert.assertThat(postTitles, Matchers.everyItem(Matchers.is("post1")));
}
</string>

Here is shown that you can easily extract repeatedly nestet items.

Tools

To test your jsonpath expression you can testers which are many on the internet.
Here you can find one of them:
https://jsonpath.curiousconcept.com/

Links

https://github.com/jayway/JsonPath
https://github.com/raphaelsolarski/jsonpath-to-test-rest-controller-example


Hamcrest collection matchers – learn by examples.

Hello.
In this post I will show how you can improve quality and clarity of your assertions using matchers in context of testing collections.

import com.google.common.collect.Lists;
import org.junit.Test;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class HamcrestCollectionsLT {

    @Test
    public void collectionShouldHasOneGivenItem() throws Exception {
        List<String> list = Lists.newArrayList("Foo");
        assertThat(list, contains("Foo"));
    }

    @Test
    public void collectionShouldHasExactlyGivenItemsInGivenOrder() throws Exception {
        List<String> list = Lists.newArrayList("Foo", "Bar");
        assertThat(list, contains("Foo", "Bar"));
    }

    @Test
    public void collectionShouldHasExactlyGivenItemsInAnyOrder() throws Exception {
        List<String> list = Lists.newArrayList("Foo", "Bar");
        assertThat(list, containsInAnyOrder("Bar", "Foo"));
    }

    @Test
    public void collectionShouldHasGivenItem() throws Exception {
        List<String> list = Lists.newArrayList("Foo", "Bar", "Element");
        assertThat(list, hasItem("Foo"));
    }

    @Test
    public void collectionShouldNotHasGivenItem() throws Exception {
        List<String> list = Lists.newArrayList("Bar", "Element");
        assertThat(list, not(hasItem("Foo")));
    }

    @Test
    public void collectionShouldBeEmpty() throws Exception {
        List<String> list = Lists.newArrayList();
        assertThat(list, empty());
    }

    @Test
    public void collectionShouldNotBeEmpty() throws Exception {
        List<String> list = Lists.newArrayList("Foo");
        assertThat(list, not(empty()));
    }

    @Test
    public void collectionShouldHasGivenLength() throws Exception {
        List<String> list = Lists.newArrayList("Foo", "Bar", "Element");
        assertThat(list, hasSize(3));
    }

    @Test
    public void collectionShouldNotHaveGivenLength() throws Exception {
        List<String> list = Lists.newArrayList("Foo");
        assertThat(list, not(hasSize(2)));
    }

    @Test
    public void everyCollectionItemShouldBeGreater() throws Exception {
        List<Integer> list = Lists.newArrayList(4, 5, 6);
        assertThat(list, everyItem(greaterThan(3)));
    }

    @Test
    public void everyCollectionItemShouldBeGreaterOrEqual() throws Exception {
        List<Integer> list = Lists.newArrayList(4, 5, 6);
        assertThat(list, everyItem(greaterThanOrEqualTo(4)));
    }

    @Test
    public void everyCollectionStringItemContainSubstring() throws Exception {
        List<String> list = Lists.newArrayList("Sub1", "Sub2", "Sub3");
        assertThat(list, everyItem(containsString("Sub")));
    }

    @Test
    public void shouldContainAtLastGivenElementsAndEveryElementShouldContainGivenString() throws Exception {
        List<String> list = Lists.newArrayList("Sub1", "Sub2", "Sub3");
        assertThat(list, allOf(hasItems("Sub1", "Sub2"), everyItem(containsString("Sub"))));
    }

}

Links:
https://github.com/hamcrest/JavaHamcrest


Spring test configuration example.

Hello.
Today I want to show you simple test configuration in spring mvc project.
In example I use java based configuration(I admit that this kind of configuration I prefer).
But in future I want to present xml based configuration, too.

On the bottom of the post you find link to github repository with full project.

Class under testing:

package com.raphaelsolarski.springtestconfig.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MyController {

    @RequestMapping(path = "/", method = RequestMethod.GET)
    String home() {
        return "home";
    }

}

Test:

package com.raphaelsolarski.springtestconfig.controller;

import com.raphaelsolarski.springtestconfig.config.WebConfig;
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.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.web.AnnotationConfigWebContextLoader;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebConfig.class}, loader = AnnotationConfigWebContextLoader.class)
@TestExecutionListeners(listeners = {DependencyInjectionTestExecutionListener.class})
@WebAppConfiguration
public class MyControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void getRootShouldReturnHomeView() throws Exception {
        mockMvc.perform(get("/")).andExpect(MockMvcResultMatchers.view().name("home"));
    }

}

github-icon Full code on github.com

Links:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html


How to compile maven project without web.xml?

When you use servlet api beyond 3.0 version, you can use java based configuration of your webapp instead of web.xml file.
Maven by default report an error when you try to compile project that does not contain web.xml file, so you have to additionally configure maven-war-plugin in pom.xml.

<plugin>
    <groupid>org.apache.maven.plugins</groupid>
    <artifactid>maven-war-plugin</artifactid>
    <version>2.2</version>
    <configuration>
        <failonmissingwebxml>false</failonmissingwebxml>
    </configuration>
</plugin>

Problem with spring @Value annotation.

Hi. Today I expirienced problem with @Value annotation in spring.
This annotation can be used to inject value from properties files in spring based applications.
I will show you a typical use case of this annotation, the problem I encountered and how I dealt with it.

foo.properties:

address=Warsaw

Foo.java:

package com.raphaelsolarski.value;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@PropertySource("classpath:foo.properties")
public class Foo {

    @Value("${address}")
    private String address;

    public String getAddress() {
        return address;
    }

}

FooTest.java:

package com.raphaelsolarski.value;

import com.raphaelsolarski.value.config.Config;
import 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;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class FooTest {

    @Autowired
    private Foo foo;

    @Test
    public void shouldReturnPropertyValue() throws Exception {
        String actual = foo.getAddress();
        String expected = "Warsaw";
        Assert.assertEquals(expected, actual);
    }

}

The test will fail with the following error:

org.junit.ComparisonFailure: 
Expected :Warsaw
Actual   :${address}

There is a simple solution. We have to declare a PropertySourcesPlaceholderConfigurer bean somewhere in spring configuration of our application.

Config.java

package com.raphaelsolarski.value.config;

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("com.raphaelsolarski.value")
public class Config {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

}

github-icon Full code on github.com


How to add filter to spring mvc in java config?

In this post I show you how to add filter in two different kinds of spring based configurations.

Configuration by WebApplicationInitializer

package raphaelsolarski.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import raphaelsolarski.filter.MyFilter;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;

public class MyWebAppInitializer implements WebApplicationInitializer {

   public void onStartup(ServletContext container) {
       //here I can set up any kind of spring context -&gt; xml/java...
       AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
       appContext.scan("raphaelsolarski");
       ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
       registration.setLoadOnStartup(1);
       registration.addMapping("/");
       container.addFilter("My filter", MyFilter.class).addMappingForServletNames(null, false, "dispatcher");
       //or container.addFilter("My filter", MyFilter.class).addMappingForUrlPatterns(null, false, "/*");
   }

}

Configuration by AbstractAnnotationConfigDispatcherServletInitializer

package com.raphaelsolarski.config;

import com.raphaelsolarski.filter.MyFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.Filter;

public class MyDispatcher extends AbstractAnnotationConfigDispatcherServletInitializer{
   @Override
   protected Class<!--?-->[] getRootConfigClasses() {
       return null;
   }

   @Override
   protected Class<!--?-->[] getServletConfigClasses() {
       return new Class<!--?-->[] {SpringConfig.class};
   }

   @Override
   protected String[] getServletMappings() {
       return new String[] {"/"};
   }

   @Override
   protected Filter[] getServletFilters() {
       return new Filter[] { new MyFilter() };
   }
}

How to configure dispatcher servlet without web.xml?

In my first post I want show you how to simply configure Dispatcher Servlet with Spring without xml code.
I will cover three types of spring configuration you may want to use(I think about cofiguration of rest of application, not about dispatcher servlet).
Java annotations driven config, xml based and mixture of both of them.

In configuration I will WebApplicationInitializer interface and AbstractDispatcherServletInitializer class.
When you want to configure dispatcher servlet in java you probably should use one of them.

Configuration by implementing WebApplicationInitializer interface:

import org.springframework.web.WebApplicationInitializer;

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        XmlWebApplicationContext appContext = new XmlWebApplicationContext();
        appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");

        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }

}

Configuration by extending AbstractDispatcherServletInitializer(for using xml based spring configuration):

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        XmlWebApplicationContext cxt = new XmlWebApplicationContext();
        cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
        return cxt;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

Configuration by extending AbstractAnnotationConfigDispatcherServletInitializer class(for java based spring configuration):

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<!--?-->[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<!--?-->[] getServletConfigClasses() {
        return new Class[] { MyWebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

Links:
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/WebApplicationInitializer.html
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-container-config