Quantcast
Channel: Baeldung
Viewing all 3703 articles
Browse latest View live

What’s New in Spring 4.3?

$
0
0

I just released the Starter Class of "Learn Spring Security":

>> CHECK OUT THE COURSE

1. Overview

The Spring 4.3 release brought some nice refinements into core container, caching, JMS, Web MVC and testing submodules of the framework.

In this post we will discuss few of these improvements including:

  • Implicit Constructor Injection
  • Java 8 Default Interface Methods Support
  • Improved Resolution of Dependencies
  • Cache Abstraction Refinements
  • Composed @RequestMapping Variants
  • @RequestScope, @SessionScope, @ApplicationScope annotations
  • @RequestAttribute and @SessionAttribute annotations
  • Libraries/Application Servers Versions Support

2. Implicit Constructor Injection

Consider the following service class:

@Service
public class FooService {

    private final FooRepository repository;

    @Autowired
    public FooService(FooRepository repository) {
        this.repository = repository
    }
}

Quite a common use case, but if you forget the @Autowired annotation on the constructor, the container will throw an exception looking for a default constructor, unless you explicitly do the wiring.

So as of 4.3, you no longer need to specify an explicit injection annotation in such a single-constructor scenario. This is particularly elegant for classes which do not carry any annotations at all:

public class FooService {

    private final FooRepository repository;

    public FooService(FooRepository repository) {
        this.repository = repository
    }
}

In Spring 4.2 and below, the following configuration for this bean will not work, because Spring will not be able to find a default constructor for FooService. Spring 4.3 is more clever and will autowire the constructor automatically:

<beans>
    <bean class="com.baeldung.spring43.ctor.FooRepository" />
    <bean class="com.baeldung.spring43.ctor.FooService" />
</beans>

Similarly, you may have noticed that @Configuration classes historically did not support constructor injection. As of 4.3, they do and they obviously allow omitting @Autowired in a single-constructor scenario as well:

@Configuration
public class FooConfiguration {

    private final FooRepository repository;

    public FooConfiguration(FooRepository repository) {
        this.repository = repository
    }

    @Bean
    public FooService fooService() {
        return new FooService(this.repository);
    }
}

3. Java 8 Default Interface Methods Support

Before Spring 4.3, default interface methods were not supported.

This was not easy to implement, because even JDK’s own JavaBean introspector did not detect default methods as accessors. Since Spring 4.3, getters and setters implemented as default interface methods are detected during injection, which allows to use them for instance as common preprocessors for accessed properties, like in this example:

public interface IDateHolder {

    void setLocalDate(LocalDate localDate);

    LocalDate getLocalDate();

    default void setStringDate(String stringDate) {
        setLocalDate(LocalDate.parse(stringDate, 
          DateTimeFormatter.ofPattern("dd.MM.yyyy")));
    }

}

This bean may now have the stringDate property injected:

<bean id="dateHolder" 
  class="com.baeldung.spring43.defaultmethods.DateHolder">
    <property name="stringDate" value="15.10.1982"/>
</bean>

Same goes for using test annotations like @BeforeTransaction and @AfterTransaction on default interface methods. JUnit 5 already supports its test annotations on default interface methods and Spring 4.3 follows the lead. Now you can abstract common testing logic in an interface and implement it in test classes. Here is an interface for test cases that logs messages before and after transactions in tests:

public interface ITransactionalTest {

    Logger log = LoggerFactory.getLogger(ITransactionalTest.class);

    @BeforeTransaction
    default void beforeTransaction() {
        log.info("Before opening transaction");
    }

    @AfterTransaction
    default void afterTransaction() {
        log.info("After closing transaction");
    }

}

Another improvement concerning annotations @BeforeTransaction, @AfterTransaction and @Transactional is the relaxation of the requirement that the annotated methods should be public — now they may have any visibility level.

4. Improved Resolution of Dependencies

The newest version introduces also the ObjectProvider, an extension of the existing ObjectFactory interface with handy signatures such as getIfAvailable and getIfUnique to retrieve a bean only if it actually exists or if a single candidate can be determined (in particular: a primary candidate in case of multiple matching beans).

@Service
public class FooService {

    private final FooRepository repository;

    public FooService(ObjectProvider<FooRepository> repositoryProvider) {
        this.repository = repositoryProvider.getIfUnique();
    }
}

You may use such ObjectProvider handle for custom resolution purposes during initialization as shown above, or store the handle in a field for late on-demand resolution (as you typically do with an ObjectFactory).

5. Cache Abstraction Refinements

The cache abstraction is mainly used to cache values that are CPU and/or IO consuming. In certain use cases, a given key may be requested by several threads (i.e. clients) in parallel, especially on startup. Synchronized cache support is a long-requested feature that has now been implemented. Assume the following:

@Service
public class FooService {

    @Cacheable(cacheNames = "foos", sync = true)
    public Foo getFoo(String id) { ... }

}

Notice the sync = true attribute which tells the framework to block any concurrent threads while the value is being computed. This will make sure that this intensive operation is invoked only once in case of concurrent access.

Spring 4.3 also improves the caching abstraction as follows:

  • SpEL expressions in cache-related annotations can now refer to beans (i.e. @beanName.method()).
  • ConcurrentMapCacheManager and ConcurrentMapCache now support the serialization of cache entries via a new storeByValue attribute.
  • @Cacheable, @CacheEvict, @CachePut, and @Caching may now be used as meta-annotations to create custom composed annotations with attribute overrides.

6. Composed @RequestMapping Variants

Spring Framework 4.3 introduces the following method-level composed variants of the @RequestMapping annotation that help to simplify mappings for common HTTP methods and better express the semantics of the annotated handler method.

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

For example, @GetMapping is a shorter form of saying @RequestMapping(method = RequestMethod.GET). The following example shows an MVC controller that has been simplified with a composed @GetMapping annotation.

@Controller
@RequestMapping("/appointments")
public class AppointmentsController {

    private final AppointmentBook appointmentBook;

    @Autowired
    public AppointmentsController(AppointmentBook appointmentBook) {
        this.appointmentBook = appointmentBook;
    }

    @GetMapping
    public Map<String, Appointment> get() {
        return appointmentBook.getAppointmentsForToday();
    }
}

7. @RequestScope, @SessionScope, @ApplicationScope annotations

When using annotation-driven components or Java Config, the @RequestScope, @SessionScope and @ApplicationScope annotations can be used to assign a component to the required scope. These annotations not only set the scope of the bean, but also set the scoped proxy mode to ScopedProxyMode.TARGET_CLASS.

TARGET_CLASS mode means that CGLIB proxy will be used for proxying of this bean and ensuring that it can be injected in any other bean, even with a broader scope. TARGET_CLASS mode allows proxying not only for interfaces, but for classes too.

@RequestScope
@Component
public class LoginAction {
    // ...
}
@SessionScope
@Component
public class UserPreferences {
    // ...
}
@ApplicationScope
@Component
public class AppPreferences {
    // ...
}

8. @RequestAttribute and @SessionAttribute annotations

Two more annotations for injecting parameters of the HTTP request into Controller methods appeared, namely @RequestAttribute and @SessionAttribute. They allow you to access some pre-existing attributes, managed globally (i.e. outside the Controller). The values for these attributes may be provided, for instance, by registered instances of javax.servlet.Filter or org.springframework.web.servlet.HandlerInterceptor.

Suppose we have registered the following HandlerInterceptor implementation that parses the request and adds an additional login parameter to the session and another query parameter to a request:

public class ParamInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, 
      HttpServletResponse response, Object handler) throws Exception {
        request.getSession().setAttribute("login", "john");
        request.setAttribute("query", "invoices");
        return super.preHandle(request, response, handler);
    }

}

Such parameters may be injected into a Controller instance with corresponding annotations on method arguments:

@GetMapping
public String get(@SessionAttribute String login, 
  @RequestAttribute String query) {
    return String.format("login = %s, query = %s", login, query);
}

9. Libraries/Application Servers Versions Support

Spring 4.3 supports the following library versions and server generations:

  • Hibernate ORM 5.2 (still supporting 4.2/4.3 and 5.0/5.1 as well, with 3.6 deprecated now)
  • Jackson 2.8 (minimum raised to Jackson 2.6+ as of Spring 4.3)
  • OkHttp 3.x (still supporting OkHttp 2.x side by side)
  • Netty 4.1
  • Undertow 1.4
  • Tomcat 8.5.2 as well as 9.0 M6

Furthermore, Spring 4.3 embeds the updated ASM 5.1 and Objenesis 2.4 in spring-core.jar.

10. Conclusion

In this article we discussed some of the new features introduced with Spring 4.3.

We’ve covered useful annotations that eliminate boilerplate, new helpful methods of dependency lookup and injection and several important improvements within web and caching facilities.

You can find the source code for the article on GitHub.

Get the early-bird price (20% Off) of my upcoming "Learn Spring Security" Course:

>> CHECK OUT THE COURSE


Mutation Testing with PITest

$
0
0

I just released the Starter Class of "Learn Spring Security":

>> CHECK OUT THE COURSE

1. Overview

Software testing refers to the techniques used to assess the functionality of a software application. In this article we’re going to discuss some of the metrics used in the software testing industry, such as code coverage and mutation testing, with peculiar interest on how to perform a mutation test using the PITest library.

For the sake of simplicity, we’re going to base this demonstration on a basic palindrome function – Note that a palindrome is a string that reads the same backward and forward.

2. Maven Dependencies

As you can see in the Maven dependencies configuration, we will use JUnit to run our tests and the PITest library to introduce mutants into our code – don’t worry, we will see in a second what a mutant is. You can always lookup the latest dependency version against the maven central repository by following this link.

<dependency>
    <groupId>org.pitest</groupId>
    <artifactId>pitest-parent</artifactId>
    <version>1.1.10</version>
    <type>pom</type>
</dependency>

In order to have the PITest library up and running, we also need to include the pitest-maven plugin in our pom.xml configuration file:

<plugin>
    <groupId>org.pitest</groupId>
    <artifactId>pitest-maven</artifactId>
    <version>1.1.10</version>
    <configuration>
        <targetClasses>
            <param>com.baeldung.testing.mutation.*</param>
        </targetClasses>
        <targetTests>
            <param>com.baeldung.mutation.test.*</param>
	</targetTests>
     </configuration>
</plugin>

3. Project Setup

Now that we have our Maven dependencies configured, let’s have a look at this self-explanatory palindrome function:

public boolean isPalindrome(String inputString) {
    if (inputString.length() == 0) {
        return true;
    } else {
        char firstChar = inputString.charAt(0);
        char lastChar = inputString.charAt(inputString.length() - 1);
        String mid = inputString.substring(1, inputString.length() - 1);
        return (firstChar == lastChar) && isPalindrome(mid);
    }
}

All we need now is a simple JUnit test to make sure that our implementation works in the desired way:

@Test
public void acceptsPalindrome() {
    Palindrome palindromeTester = new Palindrome();
    assertTrue(palindromeTester.isPalindrome("noon"));
}

So far so good, we are ready to run our test case successfully as a JUnit test.

Next in this article, we are going to focus on code and mutation coverage using the PITest library.

4. Code Coverage

Code coverage has been used extensively in the software industry, to measure what percent of the execution paths has been exercised during automated tests.

We can measure the effective code coverage based on execution paths using tools like Eclemma available on Eclipse IDE.

After running TestPalindrome with code coverage we can easily achieve a 100% coverage score – Note that isPalindrome is recursive, so it’s pretty obvious that empty input length check will be covered anyway.

Unfortunately, code coverage metrics can sometimes be quite ineffective, because a 100% code coverage score only means that all lines were exercised at least once, but it says nothing about tests accuracy or use-cases completeness, and that’s why mutation testing actually matters.

5. Mutation Coverage

Mutation testing is a testing technique used to improve the adequacy of tests, and identify defects in code. The idea is to change the production code dynamically, and cause the tests to fail.

Good tests shall fail

Each change in the code is called a mutant, and it results an altered version of the program, called a mutation.

We say that the mutation is killed, if it can cause a fail in the tests. We also say that the mutation survived if the mutant couldn’t affect the tests behavior.

Now let’s run the test using Maven, with the goal option set to: org.pitest:pitest-maven:mutationCoverage.

We can check the reports in HTML format in the target/pit-test/YYYYMMDDHHMI directory:

  • 100% line coverage: 7/7
  • 63% mutation coverage: 5/8

Clearly our test sweeps across all the execution paths, thus, the line coverage score is 100%. In the other hand the PITest library introduced 8 mutants, 5 of them were killed – Caused a fail – but 3 survived.

We can check the com.baeldung.testing.mutation/Palindrome.java.html report for more details about the mutants created:


Mutations

These are the mutators active by default when running a mutation coverage test:

  • INCREMENTS_MUTATOR
  • VOID_METHOD_CALL_MUTATOR
  • RETURN_VALS_MUTATOR
  • MATH_MUTATOR
  • NEGATE_CONDITIONALS_MUTATOR
  • INVERT_NEGS_MUTATOR
  • CONDITIONALS_BOUNDARY_MUTATOR

For more details about the PITest mutators, you can check the official documentation page link.

Our mutation coverage score reflects the lack of test cases, as we can’t make sure that our palindrome function rejects non-palindromic and near-palindromic string inputs.

6. Improve the Mutation Score

Now that we know what a mutation is, we need to improve our mutation score by killing the surviving mutants.

Let’s take the first mutation – negated conditional – on line 6 as an example. The mutant survived because even if we change the code snippet:

if (inputString.length() == 0) {
    return true;
}

To:

if (inputString.length() != 0) {
    return true;
}

The test will pass, and that’s why the mutation survived. The idea is to implement a new test that will fail, in case the mutant is introduced. The same can be done for the remaining mutants.

@Test
public void rejectsNonPalindrome() {
    Palindrome palindromeTester = new Palindrome();
    assertFalse(palindromeTester.isPalindrome("box"));
}
@Test
public void rejectsNearPalindrome() {
    Palindrome palindromeTester = new Palindrome();
    assertFalse(palindromeTester.isPalindrome("neon"));
}

Now we can run our tests using the mutation coverage plugin, to make sure that all the mutations were killed, as we can see in the PITest report generated in target directory.

  • 100% line coverage: 7/7
  • 100% mutation coverage: 8/8

7. PITest Tests Configuration

Mutation testing may be resources-extensive sometimes, so we need to put proper configuration in place to improve tests effectiveness. We can make use of the targetClasses tag, to define the list of classes to be mutated. Mutation testing cannot be applied on all classes in a real world project, as it will be time consuming, and resource critical.

It is also important to define the mutators you plan to use during mutation testing, in order to minimize the computing resources needed to perform the tests:

<configuration>
    <targetClasses>
        <param>com.baeldung.testing.mutation.*</param>
    </targetClasses>
    <targetTests>
        <param>com.baeldung.mutation.test.*</param>
    </targetTests>
    <mutators>
        <mutator>CONSTRUCTOR_CALLS</mutator>
        <mutator>VOID_METHOD_CALLS</mutator>
        <mutator>RETURN_VALS</mutator>
        <mutator>NON_VOID_METHOD_CALLS</mutator>
    </mutators>
</configuration>

Moreover, the PITest library offers a variety of options available to customize your testing strategies, you can specify the maximum number of mutants introduced by class using the maxMutationsPerClass option for example. More details about PITest options in the official Maven quickstart guide.

8. Conclusion

Note that code coverage is still an important metric, but sometimes it is not sufficient enough to guarantee a well-tested code. So in this article we’ve walked through mutation testing as a more sophisticated way to ensure tests quality and endorse test-cases, using the PITest library.

We have also seen how to analyze a basic PITest reports, while improving the mutation coverage score.

Even though mutation testing reveals defects in code, it should be used wisely, because it is an extremely costly and time-consuming process.

You can checkout the examples provided in this article in the linked GitHub project.

Get the early-bird price (20% Off) of my upcoming "Learn Spring Security" Course:

>> CHECK OUT THE COURSE

Java Web Weekly, Issue 133

$
0
0

I just released the Starter Class of "Learn Spring Security":

>> CHECK OUT THE COURSE

At the very beginning of last year, I decided to track my reading habits and share the best stuff here, on Baeldung. Haven’t missed a review since.

Here we go…

1. Spring and Java

>> Stagnation with Java EE 8: Can the Java Community Make a Difference? [infoq.com]

The Java EE story unfolding.

>> JUnit 5 M1 [marcphilipp.de]

The official announcement of the very first milestone of JUnit 5. Good stuff – it looks like it’s time to give this one a real try.

>> JUnit 5 – Dynamic Tests [codefx.org]

And speaking of the first milestone of JUnit 5, Nicolai is of course continuing to explore the very cool aspects of JUnit. This one is about the concept of a dynamic test, which can potentially be quite powerful.

>> How to Get Started with Java Machine Learning [takipi.com]

A quick overview of machine learning in the Java ecosystem. It’s a bit of a shame that Mahout has been abandoned in this space, as it was showing some promise a few years back.

>> Robot Framework Tutorial 2016 – Integration with Jenkins [codecentric.de]

Solid intro to setting up the Robot Framework with a new Jenkins 2.0 server from scratch. Definitely one to bookmark for if/when you have to do that.

>> The best way to detect database connection leaks [vladmihalcea.com]

DB connection leaks are never fun and almost never easy to find and solve. This is a good introduction to how you may handle that.

>> Stackoverflow: 7 of the Best Java Answers That You Haven’t Seen [takipi.com]

A fun an interesting idea – having a look at a few of the top questions about Java on StackOverflow.

Some of these brought me right back to the Operating Systems course in college 🙂

Also worth reading:

Webinars and presentations:

Time to upgrade:

2. Technical and Musings

>> Jepsen: VoltDB 6.3 [aphyr.com]

Another deep analysis of a persistence solution that doesn’t quite do what it advertises yet, but is on the right track to getting there.

These kinds of in-depth dives into the low level problems of a persistence implementation are priceless to really learn about the mindset, the approach and the practical way of looking things when it comes to persistence.

>> The REST Report [tbray.org]

Some thoughts about REST in the ecosystem today.

>> How Collaboration Humanizes the Enterprise [daedtech.com]

This piece is both a bit sad and a bit encouraging.

Organizations do inherently run into well-understood issues with scale, but it’s still so very rare to find an organization that is successfully navigating these issues and not just patching them up.

>> For those of you thinking about moving into the test automation field [ontestautomation.com]

Advice worth reading even if you’re not planning to do test automation full time but simply in parallel to your day to day work.

>> Benefits of Serverless Architectures [martinfowler.com]

Continuing the discussion, this piece has a look at the benefits and reasoning behind a Serverless architecture.

>> Baeldung Q2 2016 Report [meta.baeldung.com]

And the quarterly inside look at the numbers of baeldung.com is out.

If you didn’t know, I publish this report regularly giving curious readers an inside look into how the site is doing.

Also worth reading:

3. Comics

And my favorite Dilberts of the week:

>> You are entitled to a cubicle that is three inches wider [dilbert.com]

>> The extreme level of abstraction [dilbert.com]

>> Hubris? What’s that [dilbert.com]

4. Pick of the Week

>> Getting less done [signalvnoise.com]

Get the early-bird price (20% Off) of my upcoming "Learn Spring Security" Course:

>> CHECK OUT THE COURSE

3 Common Hibernate Performance Issues and How to Find Them in Your Log File

$
0
0

1. Introduction

You’ve probably read some of the complaints about bad Hibernate performance or maybe you’ve struggled with some of them yourself. I have been using Hibernate for more than 15 years now and I have run into more than enough of these issues.

Over the years, I’ve learned that these problems can be avoided and that you can find a lot of them in your log file. In this post, I want to show you how you can find and fix 3 of them.

If you like this post, make sure to read to the end of it to download a free cheat sheet with even more Hibernate performance tuning tips.

2. Find and Fix Performance Problems

2.1. Log SQL Statements in Production

The first performance issue is extremely easy to spot and often ignored. It’s the logging of SQL statements in a production environment.

Writing some log statements doesn’t sound like a big deal, and there are a lot of applications out there which do exactly that. But it is extremely inefficient, especially via System.out.println as Hibernate does it if you set the show_sql parameter in your Hibernate configuration to true:

Hibernate: select 
    order0_.id as id1_2_, 
    order0_.orderNumber as orderNum2_2_, 
    order0_.version as version3_2_ 
  from purchaseOrder order0_
Hibernate: select 
    items0_.order_id as order_id4_0_0_, 
    items0_.id as id1_0_0_, 
    items0_.id as id1_0_1_, 
    items0_.order_id as order_id4_0_1_, 
    items0_.product_id as product_5_0_1_, 
    items0_.quantity as quantity2_0_1_, 
    items0_.version as version3_0_1_ 
  from OrderItem items0_ 
  where items0_.order_id=?
Hibernate: select 
    items0_.order_id as order_id4_0_0_, 
    items0_.id as id1_0_0_, 
    items0_.id as id1_0_1_, 
    items0_.order_id as order_id4_0_1_, 
    items0_.product_id as product_5_0_1_, 
    items0_.quantity as quantity2_0_1_, 
    items0_.version as version3_0_1_ 
  from OrderItem items0_ 
  where items0_.order_id=?
Hibernate: select 
    items0_.order_id as order_id4_0_0_, 
    items0_.id as id1_0_0_, 
    items0_.id as id1_0_1_, 
    items0_.order_id as order_id4_0_1_, 
    items0_.product_id as product_5_0_1_, 
    items0_.quantity as quantity2_0_1_, 
    items0_.version as version3_0_1_ 
  from OrderItem items0_ 
  where items0_.order_id=?

In one of my projects, I improved the performance by 20% within a few minutes by setting show_sql to false. That’s the kind of achievement you like to report in the next stand-up meeting 🙂

It’s pretty obvious how you can fix this performance issue. Just open your configuration (e.g. your persistence.xml file) and set the show_sql parameter to false. You don’t need this information in production anyways.

But you might need them during development. If you don’t, you use 2 different Hibernate configurations (which you shouldn’t) you deactivated the SQL statement logging there as well. The solution for that is to use 2 different log configurations for development and production which are optimized for the specific requirements of the runtime environment.

Development Configuration

The development configuration should provide as many useful information as possible so that you can see how Hibernate interacts with the database. You should therefore at least log the generated SQL statements in your development configuration. You can do this by activating DEBUG message for the org.hibernate.SQL category. If you also want to see the values of your bind parameters, you have to set the log level of org.hibernate.type.descriptor.sql to TRACE:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n
log4j.rootLogger=info, stdout

# basic log level for all messages
log4j.logger.org.hibernate=info

# SQL statements and parameters
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type.descriptor.sql=trace

The following code snippet shows some example log messages which Hibernate writes with this log configuration. As you can see, you get detailed information about the executed SQL query and all set and retrieved parameter values:

23:03:22,246 DEBUG SQL:92 - select 
    order0_.id as id1_2_, 
    order0_.orderNumber as orderNum2_2_, 
    order0_.version as version3_2_ 
  from purchaseOrder order0_ 
  where order0_.id=1
23:03:22,254 TRACE BasicExtractor:61 - extracted value ([id1_2_] : [BIGINT]) - [1]
23:03:22,261 TRACE BasicExtractor:61 - extracted value ([orderNum2_2_] : [VARCHAR]) - [order1]
23:03:22,263 TRACE BasicExtractor:61 - extracted value ([version3_2_] : [INTEGER]) - [0]

Hibernate provides you with a lot more internal information about a Session if you activate the Hibernate statistics. You can do this by setting the system property hibernate.generate_statistics to true.

But please, only activate the statistics on your development or test environment. Collecting all these information slows down your application and you might create your performance problems yourself if you activate it this in production.

You can see some example statistics in the following code snippet:

23:04:12,123 INFO StatisticalLoggingSessionEventListener:258 - Session Metrics {
 23793 nanoseconds spent acquiring 1 JDBC connections;
 0 nanoseconds spent releasing 0 JDBC connections;
 394686 nanoseconds spent preparing 4 JDBC statements;
 2528603 nanoseconds spent executing 4 JDBC statements;
 0 nanoseconds spent executing 0 JDBC batches;
 0 nanoseconds spent performing 0 L2C puts;
 0 nanoseconds spent performing 0 L2C hits;
 0 nanoseconds spent performing 0 L2C misses;
 9700599 nanoseconds spent executing 1 flushes (flushing a total of 9 entities and 3 collections);
 42921 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}

I regularly use these statistics in my daily work to find performance issues before they occur in production and I could write several posts just about that. So let’s just focus on the most important ones.

The lines 2 to 5 show you how many JDBC connections and statements Hibernate used during this session and how much time it spent on it. You should always have a look at these values and compare them with your expectations.

If there are a lot more statements than you expected, you most likely have the most common performance problem, the n+1 select issue. You can find it in nearly all applications, and it might create huge performance issues on a bigger database. I explain this issue in more details in the next section.

The lines 7 to 9 show how Hibernate interacted with the 2nd level cache. This is one of Hibernate’s 3 caches, and it stores entities in a session independent way. If you use the 2nd level in your application, you should always monitor these statistics to see if Hibernate gets the entities from there.

Production Configuration

The production configuration should be optimized for performance and avoid any messages that are not urgently required. In general, that means that you should only log error messages. If you use Log4j, you can achieve that with the following configuration:

If you use Log4j, you can achieve that with the following configuration:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n
log4j.rootLogger=info, stdout

# basic log level for all messages
log4j.logger.org.hibernate=error

2.2. N+1 Select Issue

As I already explained, the n+1 select issue is the most common performance problem. A lot of developers blame the OR-Mapping concept for this issue, and they’re not completely wrong. But you can easily avoid it if you understand how Hibernate treats lazily fetched relationships. The developer is, therefore, to blame as well because it’s his responsibility to avoid these kinds of issues. So let me explain first why this issue exists and then show you an easy way to prevent it. If you are already familiar with the n+1 select issues, you can jump directly to the solution.

Hibernate provides a very convenient mapping for relationships between entities. You just need an attribute with the type of the related entity and a few annotations to define it:

@Entity
@Table(name = "purchaseOrder")
public class Order implements Serializable {

    @OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
    private Set<OrderItem> items = new HashSet<OrderItem>();

    ...
}

When you now load an Order entity from the database, you just need to call the getItems() method to get all items of this order. Hibernate hides the required database queries to get the related OrderItem entities from the database.

When you started with Hibernate, you probably learned that you should use FetchType.LAZY for most of the relationships and that it’s the default for to-many relationships. This tells Hibernate to only fetch the related entities if you use the attribute which maps the relationship. Fetching only the data you need is a good thing in general, but it also requires Hibernate to execute an additional query to initialize each relationship. This can result in a huge number of queries, if you work on a list of entities, like I do in the following code snippet:

List<Order> orders = em.createQuery("SELECT o FROM Order o").getResultList();
for (Order order : orders) {
    log.info("Order: " + order.getOrderNumber());
    log.info("Number of items: " + order.getItems().size());
}

You probably wouldn’t expect that this few lines of code can create hundreds or even thousands of database queries. But it does if you use FetchType.LAZY for the relationship to the OrderItem entity:

22:47:30,065 DEBUG SQL:92 - select 
    order0_.id as id1_2_, 
    order0_.orderNumber as orderNum2_2_, 
    order0_.version as version3_2_ 
  from purchaseOrder order0_
22:47:30,136 INFO NamedEntityGraphTest:58 - Order: order1
22:47:30,140 DEBUG SQL:92 - select 
    items0_.order_id as order_id4_0_0_, 
    items0_.id as id1_0_0_, 
    items0_.id as id1_0_1_, 
    items0_.order_id as order_id4_0_1_, 
    items0_.product_id as product_5_0_1_, 
    items0_.quantity as quantity2_0_1_, 
    items0_.version as version3_0_1_ 
  from OrderItem items0_ 
  where items0_.order_id=?
22:47:30,171 INFO NamedEntityGraphTest:59 - Number of items: 2
22:47:30,171 INFO NamedEntityGraphTest:58 - Order: order2
22:47:30,172 DEBUG SQL:92 - select 
    items0_.order_id as order_id4_0_0_, 
    items0_.id as id1_0_0_, 
    items0_.id as id1_0_1_, 
    items0_.order_id as order_id4_0_1_, 
    items0_.product_id as product_5_0_1_, 
    items0_.quantity as quantity2_0_1_, 
    items0_.version as version3_0_1_ 
  from OrderItem items0_ 
  where items0_.order_id=?
22:47:30,174 INFO NamedEntityGraphTest:59 - Number of items: 2
22:47:30,174 INFO NamedEntityGraphTest:58 - Order: order3
22:47:30,174 DEBUG SQL:92 - select 
    items0_.order_id as order_id4_0_0_, 
    items0_.id as id1_0_0_, 
    items0_.id as id1_0_1_, 
    items0_.order_id as order_id4_0_1_, 
    items0_.product_id as product_5_0_1_, 
    items0_.quantity as quantity2_0_1_, 
    items0_.version as version3_0_1_ 
  from OrderItem items0_ 
  where items0_.order_id=?
22:47:30,176 INFO NamedEntityGraphTest:59 - Number of items: 2

Hibernate performs one query to get all Order entities and an additional one for each of the n Order entities to initialize the orderItem relationship. So you now know why this kind of issue is called n+1 select issue and why it can create huge performance problems.

What makes it even worse is, that you often don’t recognize it on a small test database, if you haven’t checked your Hibernate statistics. The code snippet requires only a few dozen queries if the test database doesn’t contain a lot of orders. But that will be completely different if you use your productive database which contains several thousand of them.

I said earlier that you can easily avoid these issues. And that’s true. You just have to initialize the orderItem relationship when you select the Order entities from the database.

But please, only do that, if you use the relationship in your business code and don’t use FetchType.EAGER to always fetch the related entities. That just replaces your n+1 issue with another performance problem.

Initialize a Relationships with a @NamedEntityGraph

There are several different options to initialize relationships. I prefer to use a @NamedEntityGraph which is is one of my favorite features introduced in JPA 2.1. It provides a query independent way to specify a graph of entities which Hibernate shall fetch from the database. In following code snippet, you can see an example of a simple graph that lets Hibernate eagerly fetch the items attribute of an entity:

@Entity
@Table(name = "purchase_order")
@NamedEntityGraph(
  name = "graph.Order.items", 
  attributeNodes = @NamedAttributeNode("items"))
public class Order implements Serializable {

    ...
}

There isn’t much you need to do to define an entity graph with a @NamedEntityGraph annotation. You just have to provide a unique name for the graph and one @NamedAttributeNode annotation for each attribute Hibernate shall fetch eagerly. In this example, it’s only the items attribute which maps the relationship between an Order and several OrderItem entities.

Now you can use the entity graph to control the fetching behaviour or a specific query. You, therefore, have to instantiate an EntityGraph based on the @NamedEntityGraph definition and provide it as a hint to the EntityManager.find() method or your query. I do this in the following code snippet where I select the Order entity with id 1 from the database:

EntityGraph graph = this.em.getEntityGraph("graph.Order.items");

Map hints = new HashMap();
hints.put("javax.persistence.fetchgraph", graph);

return this.em.find(Order.class, 1L, hints);

Hibernate uses this information to create one SQL statement which gets the attributes of the Order entity and the attributes of the entity graph from the database:

17:34:51,310 DEBUG [org.hibernate.loader.plan.build.spi.LoadPlanTreePrinter] (pool-2-thread-1) 
  LoadPlan(entity=blog.thoughts.on.java.jpa21.entity.graph.model.Order) 
    - Returns 
      - EntityReturnImpl(
          entity=blog.thoughts.on.java.jpa21.entity.graph.model.Order, 
          querySpaceUid=<gen:0>, 
          path=blog.thoughts.on.java.jpa21.entity.graph.model.Order) 
        - CollectionAttributeFetchImpl(
            collection=blog.thoughts.on.java.jpa21.entity.graph.model.Order.items, 
            querySpaceUid=<gen:1>, 
            path=blog.thoughts.on.java.jpa21.entity.graph.model.Order.items)
          - (collection element) CollectionFetchableElementEntityGraph(
              entity=blog.thoughts.on.java.jpa21.entity.graph.model.OrderItem, 
              querySpaceUid=<gen:2>, 
              path=blog.thoughts.on.java.jpa21.entity.graph.model.Order.items.<elements>) 
            - EntityAttributeFetchImpl(entity=blog.thoughts.on.java.jpa21.entity.graph.model.Product,
                querySpaceUid=<gen:3>, 
                path=blog.thoughts.on.java.jpa21.entity.graph.model.Order.items.<elements>.product) 
    - QuerySpaces 
      - EntityQuerySpaceImpl(uid=<gen:0>, entity=blog.thoughts.on.java.jpa21.entity.graph.model.Order)
        - SQL table alias mapping - order0_ 
        - alias suffix - 0_ 
        - suffixed key columns - {id1_2_0_} 
        - JOIN (JoinDefinedByMetadata(items)) : <gen:0> -> <gen:1> 
          - CollectionQuerySpaceImpl(uid=<gen:1>, 
              collection=blog.thoughts.on.java.jpa21.entity.graph.model.Order.items) 
            - SQL table alias mapping - items1_ 
            - alias suffix - 1_ 
            - suffixed key columns - {order_id4_2_1_} 
            - entity-element alias suffix - 2_ 
            - 2_entity-element suffixed key columns - id1_0_2_ 
            - JOIN (JoinDefinedByMetadata(elements)) : <gen:1> -> <gen:2> 
              - EntityQuerySpaceImpl(uid=<gen:2>, 
                  entity=blog.thoughts.on.java.jpa21.entity.graph.model.OrderItem) 
                - SQL table alias mapping - items1_ 
                - alias suffix - 2_ 
                - suffixed key columns - {id1_0_2_}
                - JOIN (JoinDefinedByMetadata(product)) : <gen:2> -> <gen:3> 
                  - EntityQuerySpaceImpl(uid=<gen:3>, 
                      entity=blog.thoughts.on.java.jpa21.entity.graph.model.Product) 
                    - SQL table alias mapping - product2_ 
                    - alias suffix - 3_ 
                    - suffixed key columns - {id1_1_3_}
17:34:51,311 DEBUG [org.hibernate.loader.entity.plan.EntityLoader] (pool-2-thread-1) 
  Static select for entity blog.thoughts.on.java.jpa21.entity.graph.model.Order [NONE:-1]: 
  select order0_.id as id1_2_0_, 
    order0_.orderNumber as orderNum2_2_0_, 
    order0_.version as version3_2_0_, 
    items1_.order_id as order_id4_2_1_, 
    items1_.id as id1_0_1_, 
    items1_.id as id1_0_2_, 
    items1_.order_id as order_id4_0_2_, 
    items1_.product_id as product_5_0_2_, 
    items1_.quantity as quantity2_0_2_, 
    items1_.version as version3_0_2_, 
    product2_.id as id1_1_3_, 
    product2_.name as name2_1_3_, 
    product2_.version as version3_1_3_ 
  from purchase_order order0_ 
    left outer join OrderItem items1_ on order0_.id=items1_.order_id 
    left outer join Product product2_ on items1_.product_id=product2_.id 
  where order0_.id=?

Initializing only one relationship is good enough for a blog post but in a real project, you will most likely want to build more complex graphs. So let’s do that.
You can, of course, provide an array of @NamedAttributeNode annotations to fetch multiple attributes of the same entity and you can use @NamedSubGraph to define the fetching behaviour for an additional level of entities. I use that in the following code snippet to fetch not only all related OrderItem entities but also the Product entity for each OrderItem:

@Entity
@Table(name = "purchase_order")
@NamedEntityGraph(
  name = "graph.Order.items", 
  attributeNodes = @NamedAttributeNode(value = "items", subgraph = "items"), 
  subgraphs = @NamedSubgraph(name = "items", attributeNodes = @NamedAttributeNode("product")))
public class Order implements Serializable {

    ...
}

As you can see, the definition of a @NamedSubGraph is very similar to the definition of a @NamedEntityGraph. You can then reference this subgraph in a @NamedAttributeNode annotation to define the fetching behaviour for this specific attribute.

The combination of these annotations allows you to define complex entity graphs which you can use to initialize all relationships you use in your use case and avoid n+1 select issues. If you want to specify your entity graph dynamically at runtime, you can do this also via a Java API.

2.3. Update Entities One by One

Updating entities one by one feels very natural if you think in an object oriented way. You just get the entities you want to update and call a few setter methods to change their attributes like you do it with any other object.

This approach works fine if you only change a few entities. But it gets very inefficient when you work with a list of entities and is the third performance issues you can easily spot in your log file. You just have to look for a bunch SQL UPDATE statements that look completely the same, as you can see in the following log file:

22:58:05,829 DEBUG SQL:92 - select 
  product0_.id as id1_1_, 
  product0_.name as name2_1_, 
  product0_.price as price3_1_, 
  product0_.version as version4_1_ from Product product0_
22:58:05,883 DEBUG SQL:92 - update Product set name=?, price=?, version=? where id=? and version=?
22:58:05,889 DEBUG SQL:92 - update Product set name=?, price=?, version=? where id=? and version=?
22:58:05,891 DEBUG SQL:92 - update Product set name=?, price=?, version=? where id=? and version=?
22:58:05,893 DEBUG SQL:92 - update Product set name=?, price=?, version=? where id=? and version=?
22:58:05,900 DEBUG SQL:92 - update Product set name=?, price=?, version=? where id=? and version=?

The relational representation of the database records is a much better fit for these use cases than the object oriented one. With SQL, you could just write one SQL statement that updates all the records you want to change.

You can do the same with Hibernate if you use JPQL, native SQL or the CriteriaUpdate API. All 3 of very similar, so let’s use JPQL in this example.

You can define a JPQL UPDATE statement in a similar way as you know it from SQL. You just define which entity you want to update, how to change the values of its attributes and limit the affected entities in the WHERE statement.
You can see an example of it in the following code snippet where I increase the price of all products by 10%:

em.createQuery("UPDATE Product p SET p.price = p.price*0.1").executeUpdate();

Hibernate creates an SQL UPDATE statement based on the JPQL statement and sends it to the database which performs the update operation.

It’s pretty obvious that this approach is a lot faster if you have to update a huge number entities. But it also has a drawback. Hibernate doesn’t know which entities are affected by the update operation and doesn’t update its 1st level cache. You should, therefore, make sure not to read and update an entity with a JPQL statement within the same Hibernate Session or you have to detach it to remove it from the cache.

3. Summary and Performance Cheat Sheet

Within this post, I’ve shown you 3 Hibernate performance issues which you can find in your log files.

2 of them were caused by a huge number of SQL statements. This a common reason for performance issues, if you work with Hibernate. Hibernate hides the database access behind its API and that makes it often difficult to guess the actual number of SQL statements. You should therefore always check the executed SQL statements when you make a change to your persistence tier.

If you like to learn more Hibernate performance tuning, make sure to download my cheat sheet with 7 Hibernate Performance Tuning Tips.

Guide to Java 8 Collectors

$
0
0

I just released the Starter Class of "Learn Spring Security":

>> CHECK OUT THE COURSE

1. Overview

In this tutorial we will be going through Java 8’s Collectors, which are used at the final step of processing a Stream.

If you want to read more about Stream API itself, check this article.

2. Collect Method

Stream.collect() is one of the Java 8’s Stream API‘s terminal methods. It allows to perform mutable fold operations (repackaging elements to some data structures and applying some additional logic, concatenating them, etc.) on data elements held in a Stream instance.

The strategy for this operation is provided via Collector interface implementation.

3. Collectors

All predefined implementations can be found in the Collectors class. It’s a common practice to use a following static import with them in order to leverage increased readability:

import static java.util.stream.Collectors.*;

or just single import collectors of your choice:

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;

In the following examples we will be reusing the following list:

List<String> givenList = Arrays.asList("a", "bb", "ccc", "dd");

3.1. Collectors.toList()

ToList collector can be used for collecting all Stream elements into an List instance. The important thing to remember is the fact that we can’t assume any particular List implementation with this method. If you want to have more control over this, use toCollection instead.

Let’s create a Stream instance representing a sequence of elements and collect them into an List instance:

List<String> result = givenList.stream()
  .collect(toList());

3.2. Collectors.toSet()

ToSet collector can be used for collecting all Stream elements into an Set instance. The important thing to remember is the fact that we can’t assume any particular Set implementation with this method. If you want to have more control over this, use toCollection instead.

Let’s create a Stream instance representing a sequence of elements and collect them into an Set instance:

Set<String> result = givenList.stream()
  .collect(toSet());

3.3. Collectors.toCollection()

As you probably already noticed, when using toSet and toList collectors, you can’t make any assumptions of their implementations. If you want to use a custom implementation, you will need to use the toCollection collector with a provided collection of your choice.

Let’s create a Stream instance representing a sequence of elements and collect them into an LinkedList instance:

List<String> result = givenList.stream()
  .collect(toCollection(LinkedList::new))

Notice that this will not work with any immutable collections. In such case you would need to either write a custom Collector implementation or use collectingAndThen.

3.4. Collectors.toMap()

ToMap collector can be used to collect Stream elements into a Map instance. In order to do this, you need to provide two functions:

  • keyMapper
  • valueMapper

keyMapper will be used for extracting a Map key from a Stream element and valueMapper will be used for extracting a value associated with a given key.

Let’s collect those elements into a Map that stores strings as keys and their lengths as values:

Map<String, Integer> result = givenList.stream()
  .collect(toMap(Function.identity(), String::length))

Function.identity() is just a shortcut for defining function that accept and return the same value;

Sometimes you might encounter a situation where you might end up with a key collision. In such case you should use toMap with another signature.

Map<String, Integer> result = givenList.stream()
  .collect(toMap(Function.identity(), String::length, (i1, i2) -> i1));

The third argument here is a BinaryOperator, where you can specify how you want collisions to be handled. In this case we will just pick any of these two colliding values, because we know that same strings will always have same lengths too.

3.5. Collectors.collectingAndThen()

CollectingAndThen is a special collector that allows to perform another action on a Collector’s result straight after collecting ends.

Let’s collect Stream elements to a List instance and then convert the result into an ImmutableList instance:

List<String> result = givenList.stream()
  .collect(collectingAndThen(toList(), ImmutableList::copyOf))

3.6. Collectors.joining()

Joining collector can be used for joining Stream<String> elements.

We can join them together by doing:

String result = givenList.stream()
  .collect(joining());

which will result in:

"abbcccdd"

You can also specify custom separators, prefixes, postfixes:

String result = givenList.stream()
  .collect(joining(" "));

which will result in:

"a bb ccc dd"

or you can write:

String result = givenList.stream()
  .collect(joining(" ", "PRE-", "-POST"));

which will result in:

"PRE-a bb ccc dd-POST"

3.7. Collectors.counting()

Counting is a simple collector that allows simply counting of all Stream elements.

Now we can write:

Long result = givenList.stream()
  .collect(counting());

3.8. Collectors.summarizingDouble/Long/Int()

SummarizingDouble/Long/Int is a collector that returns a special class containing statistical information about numerical data in a Stream of extracted elements.

We can obtain information about string lengths by doing:

DoubleSummaryStatistics result = givenList.stream()
  .collect(summarizingDouble(String::length));

In this case following will be true:

assertThat(result.getAverage()).isEqualTo(2);
assertThat(result.getCount()).isEqualTo(4);
assertThat(result.getMax()).isEqualTo(3);
assertThat(result.getMin()).isEqualTo(1);
assertThat(result.getSum()).isEqualTo(8);

3.9. Collectors.averagingDouble/Long/Int()

AveragingDouble/Long/Int is a collector that simply returns an average of extracted elements.

We can get average string length by doing:

Double result = givenList.stream()
  .collect(averagingDouble(String::length));

3.10. Collectors.summingDouble/Long/Int()

SummingDouble/Long/Int is a collector that simply returns a sum ofextracted elements.

We can get a sum of all string lengths by doing:

Double result = givenList.stream()
  .collect(summingDouble(String::length));

3.11. Collectors.maxBy()/minBy()

MaxBy/MinBy collectors return the biggest/the smallest element of a Stream according to a provided Comparator instance.

We can pick the biggest element by doing:

Optional<String> result = givenList.stream()
  .collect(maxBy(Comparator.naturalOrder()));

Notice that returned value is wrapped in an Optional instance. This forces users to rethink the empty collection cornercase.

3.12. Collectors.groupingBy()

GroupingBy collector is used for grouping objects by some property and storing results in a Map instance.

We can group them by string length and store grouping results in Set instances:

Map<Integer, Set<String>> result = givenList.stream()
  .collect(groupingBy(String::length, toSet()));

This will result in following being true:

assertThat(result)
  .containsEntry(1, newHashSet("a", "b"))
  .containsEntry(2, newHashSet("bb"))
  .containsEntry(3, newHashSet("ccc"))
  .containsEntry(4, newHashSet("dd"));

Notice that the second argument of the groupingBy method is actually a Collector and you are free to use any Collector of your choice.

3.13. Collectors.partitioningBy

PartitioningBy is a specialized case of groupingBy that accepts a Predicate instance and collects Stream elements into a Map instance that stores Boolean values as keys and collections as values. Under the “true” key, you can find a collection of elements matching the given Predicate and under the “false” key, you can find a collection of elements not matching the given Predicate.

You can write:

Map<Boolean, List<String>> result = givenList.stream()
  .collect(partitioningBy(s -> s.length() > 2))

Which results in a Map containing:

{false=["a", "bb", "dd"], true=["ccc"]}

4. Custom Collectors

If you want to write your own Collector implementation, you need to implement Collector interface and specify its 3 generic parameters:

public interface Collector<T, A, R> {...}
  1. T – the type of objects that will be available for collection,
  2. A – the type of an mutable accumulator object,
  3. R – the type of a final result.

Let’s write an example Collector for collecting elements into an ImmutableSet instance. We start by specifying the right types:

private class ImmutableSetCollector<T>
  implements Collector<T, ImmutableSet.Builder<T>, ImmutableSet<T>> {...}

Since we need a mutable collection for internal collection operation handling, we can’t use ImmutableSet for this, we need to use some other mutable collection or any other class that could temporarily accumulate objects for us.
In this case we will go on with a ImmutableSet.Builder and now we need to implement 5 methods:

  • Supplier<ImmutableSet.Builder<T>> supplier()
  • BiConsumer<ImmutableSet.Builder<T>, T> accumulator()
  • BinaryOperator<ImmutableSet.Builder<T>> combiner()
  • Function<ImmutableSet.Builder<T>, ImmutableSet<T>> finisher()
  • Set<Characteristics> characteristics()

supplier() method returns a Supplier instance that generates an empty accumulator instance, so in this case we can simply write:

@Override
public Supplier<ImmutableSet.Builder<T>> supplier() {
    return ImmutableSet::builder;
}

accumulator() method returns a function that is used for adding a new element to an existing accumulator object, so let’s just use the Builder‘s add method.

@Override
public BiConsumer<ImmutableSet.Builder<T>, T> accumulator() {
    return ImmutableSet.Builder::add;
}

combiner() method returns a function that is used for merging two accumulators together:

@Override
public BinaryOperator<ImmutableSet.Builder<T>> combiner() {
    return (left, right) -> left.addAll(right.build());
}

finisher() method returns a function that is used for converting an accumulator to final result type, so in this case we will just use Builder‘s build method:

@Override
public Function<ImmutableSet.Builder<T>, ImmutableSet<T>> finisher() {
    return ImmutableSet.Builder::build;
}

characteristics() method is used to provide Stream with some additional information that will be used for internal optimizations. In this case we do not pay attention to the elements order in a Set, so we will use Characteristics.UNORDERED. In order to obtain more information regarding this subject,  check Characteristics‘ JavaDoc.

@Override public Set<Characteristics> characteristics() {
    return Sets.immutableEnumSet(Characteristics.UNORDERED);
}

Here is the complete implementation along with the usage:

public class ImmutableSetCollector<T>
  implements Collector<T, ImmutableSet.Builder<T>, ImmutableSet<T>> {

@Override
public Supplier<ImmutableSet.Builder<T>> supplier() {
    return ImmutableSet::builder;
}

@Override
public BiConsumer<ImmutableSet.Builder<T>, T> accumulator() {
    return ImmutableSet.Builder::add;
}

@Override
public BinaryOperator<ImmutableSet.Builder<T>> combiner() {
    return (left, right) -> left.addAll(right.build());
}

@Override
public Function<ImmutableSet.Builder<T>, ImmutableSet<T>> finisher() {
    return ImmutableSet.Builder::build;
}

@Override
public Set<Characteristics> characteristics() {
    return Sets.immutableEnumSet(Characteristics.UNORDERED);
}

public static <T> ImmutableSetCollector<T> toImmutableSet() {
    return new ImmutableSetCollector<>();
}

and here in action:

List<String> givenList = Arrays.asList("a", "bb", "ccc", "dddd");

ImmutableSet<String> result = givenList.stream()
  .collect(toImmutableSet());

5. Conclusion

In this article we explored in depth Java 8’s collectors and showed how to implement a custom collector.

All code examples are available on the GitHub.

Get the early-bird price (20% Off) of my upcoming "Learn Spring Security" Course:

>> CHECK OUT THE COURSE

Supercharge Java Authentication with JSON Web Tokens (JWTs)

$
0
0

Getting ready to build, or struggling with, secure authentication in your Java application? Unsure of the benefits of using tokens (and specifically JSON web tokens), or how they should be deployed? I’m excited to answer these questions, and more, for you in this tutorial!

Before we dive into JSON Web Tokens (JWTs), and the JJWT library (created by Stormpath‘s CTO, Les Hazlewood and maintained by a community of contributors), let’s cover some basics.

1. Authentication vs. Token Authentication

The set of protocols an application uses to confirm user identity is authentication. Applications have traditionally persisted identity through session cookies. This paradigm relies on server-side storage of session IDs which forces developers to create session storage that is either unique and server-specific, or implemented as a completely separate session storage layer.

Token authentication was developed to solve problems server-side session IDs didn’t, and couldn’t. Just like traditional authentication, users present verifiable credentials, but are now issued a set of tokens instead of a session ID. The initial credentials could be the standard username/password pair, API keys, or even tokens from another service. (Stormpath’s API Key Authentication Feature is an example of this.)

1.1 Why Tokens?

Very simply, using tokens in place of session IDs can lower your server load, streamline permission management, and provide better tools for supporting a distributed or cloud-based infrastructure. In the case of JWT, this is primarily accomplished through the stateless nature of these types of tokens (more on that below).

Tokens offer a wide variety of applications, including: Cross Site Request Forgery (CSRF) protection schemes, OAuth 2.0 interactions, session IDs, and (in cookies) as authentication representations. In most cases, standards do not specify a particular format for tokens. Here’s an example of a typical Spring Security CSRF token in an HTML form:

<input name="_csrf" type="hidden" 
  value="f3f42ea9-3104-4d13-84c0-7bcb68202f16"/>

If you try to post that form without the right CSRF token, you get an error response, and that’s the utility of tokens. The above example is a “dumb” token. This means there is no inherent meaning to be gleaned from the token itself. This is also where JWTs make a big difference.

2. What’s in a JWT?

JWTs (pronounced “jots”) are URL-safe, encoded, cryptographically signed (sometimes encrypted) strings that can be used as tokens in a variety of applications. Here’s an example of a JWT being used as a CSRF token:

<input name="_csrf" type="hidden" 
  value="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJlNjc4ZjIzMzQ3ZTM0MTBkYjdlNjg3Njc4MjNiMmQ3MCIsImlhdCI6MTQ2NjYzMzMxNywibmJmIjoxNDY2NjMzMzE3LCJleHAiOjE0NjY2MzY5MTd9.rgx_o8VQGuDa2AqCHSgVOD5G68Ld_YYM7N7THmvLIKc"/>

In this case, you can see that the token is much longer than in our previous example. Just like we saw before, if the form is submitted without the token you get an error response.

So, why JWT?

The above token is cryptographically signed and therefore can be verified, providing proof that it hasn’t been tampered with. Also, JWTs are encoded with a variety of additional information.

Let’s look at the anatomy of a JWT to better understand how we squeeze all this goodness out of it. You may have noticed that there are three distinct sections separated by periods (.):

Header eyJhbGciOiJIUzI1NiJ9
Payload eyJqdGkiOiJlNjc4ZjIzMzQ3ZTM0MTBkYjdlNjg3Njc4MjNiMmQ3MCIsImlhdC
I6MTQ2NjYzMzMxNywibmJmIjoxNDY2NjMzMzE3LCJleHAiOjE0NjY2MzY5MTd9
Signature rgx_o8VQGuDa2AqCHSgVOD5G68Ld_YYM7N7THmvLIKc

Each section is base64 URL-encoded. This ensures that it can be used safely in a URL (more on this later). Let’s take a closer look at each section individually.

2.1. The Header

If you base64 to decode the header, you will get the following JSON string:

{"alg":"HS256"}

This shows that the JWT was signed with HMAC using SHA-256.

2.2. The Payload

If you decode the payload, you get the following JSON string (formatted for clarity):

{
  "jti": "e678f23347e3410db7e68767823b2d70",
  "iat": 1466633317,
  "nbf": 1466633317,
  "exp": 1466636917
}

Within the payload, as you can see, there are a number of keys with values. These keys are called “claims” and the JWT specification has seven of these specified as “registered” claims. They are:

iss Issuer
sub Subject
aud Audience
exp Expiration
nbf Not Before
iat Issued At
jti JWT ID

When building a JWT, you can put in any custom claims you wish. The list above simply represents the claims that are reserved both in the key that is used and the expected type. Our CSRF has a JWT ID, an “Issued At” time, a “Not Before” time, and an Expiration time. The expiration time is exactly one minute past the issued at time.

2.3. The Signature

Finally, the signature section is created by taking the header and payload together (with the . in between) and passing it through the specified algorithm (HMAC using SHA-256, in this case) along with a known secret. Note that the secret is always a byte array, and should be of a length that makes sense for the algorithm used. Below, I use a random base64 encoded string (for readability) that’s converted into a byte array.

It looks like this in pseudo-code:

computeHMACSHA256(
    header + "." + payload, 
    base64DecodeToByteArray("4pE8z3PBoHjnV1AhvGk+e8h2p+ShZpOnpr8cwHmMh1w=")
)

As long as you know the secret, you can generate the signature yourself and compare your result to the signature section of the JWT to verify that it has not been tampered with. Technically, a JWT that’s been cryptographically signed is called a JWS. JWTs can also be encrypted and would then be called a JWE. (In actual practice, the term JWT is used to describe JWEs and JWSs.)

This brings us back to the benefits of using a JWT as our CSRF token. We can verify the signature and we can use the information encoded in the JWT to confirm its validity. So, not only does the string representation of the JWT need to match what’s stored server-side, we can ensure that it’s not expired simply by inspecting the exp claim. This saves the server from maintaining additional state.

Well, we’ve covered a lot of ground here. Let’s dive into some code!

3. Setup the JJWT Tutorial

JJWT (https://github.com/jwtk/jjwt) is a Java library providing end-to-end JSON Web Token creation and verification. Forever free and open-source (Apache License, Version 2.0), it was designed with a builder-focused interface hiding most of its complexity.

The primary operations in using JJWT involve building and parsing JWTs. We’ll look at these operations next, then get into some extended features of the JJWT, and finally, we’ll see JWTs in action as CSRF tokens in a Spring Security, Spring Boot application.

The code demonstrated in the following sections can be found here. Note: The project uses Spring Boot from the beginning as its easy to interact with the API that it exposes.

To build the project, execute the following:

git clone https://github.com/eugenp/tutorials.git
cd tutorials/jjwt
mvn clean install

One of the great things about Spring Boot is how easy it is to fire up an application. To run the JJWT Fun application, simply do the following:

java -jar target/*.jar

There are ten endpoints exposed in this example application (I use httpie to interact with the application. It can be found here.)

http localhost:8080
Available commands (assumes httpie - https://github.com/jkbrzt/httpie):

  http http://localhost:8080/
	This usage message

  http http://localhost:8080/static-builder
	build JWT from hardcoded claims

  http POST http://localhost:8080/dynamic-builder-general claim-1=value-1 ... [claim-n=value-n]
	build JWT from passed in claims (using general claims map)

  http POST http://localhost:8080/dynamic-builder-specific claim-1=value-1 ... [claim-n=value-n]
	build JWT from passed in claims (using specific claims methods)

  http POST http://localhost:8080/dynamic-builder-compress claim-1=value-1 ... [claim-n=value-n]
	build DEFLATE compressed JWT from passed in claims

  http http://localhost:8080/parser?jwt=<jwt>
	Parse passed in JWT

  http http://localhost:8080/parser-enforce?jwt=<jwt>
	Parse passed in JWT enforcing the 'iss' registered claim and the 'hasMotorcycle' custom claim

  http http://localhost:8080/get-secrets
	Show the signing keys currently in use.

  http http://localhost:8080/refresh-secrets
	Generate new signing keys and show them.

  http POST http://localhost:8080/set-secrets 
    HS256=base64-encoded-value HS384=base64-encoded-value HS512=base64-encoded-value
	Explicitly set secrets to use in the application.

In the sections that follow, we will examine each of these endpoints and the JJWT code contained in the handlers.

4. Building JWTs with JJWT

Because of JJWT’s fluent interface, the creation of the JWT is basically a three-step process:

  1. The definition of the internal claims of the token, like Issuer, Subject, Expiration, and ID.
  2. The cryptographic signing of the JWT (making it a JWS).
  3. The compaction of the JWT to a URL-safe string, according to the JWT Compact Serialization rules.

The final JWT will be a three-part base64-encoded string, signed with the specified signature algorithm, and using the provided key. After this point, the token is ready to be shared with the another party.

Here’s an example of the JJWT in action:

String jws = Jwts.builder()
  .setIssuer("Stormpath")
  .setSubject("msilverman")
  .claim("name", "Micah Silverman")
  .claim("scope", "admins")
  // Fri Jun 24 2016 15:33:42 GMT-0400 (EDT)
  .setIssuedAt(Date.from(Instant.ofEpochSecond(1466796822L)))
  // Sat Jun 24 2116 15:33:42 GMT-0400 (EDT)
  .setExpiration(Date.from(Instant.ofEpochSecond(4622470422L)))
  .signWith(
    SignatureAlgorithm.HS256,
    TextCodec.BASE64.decode("Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=")
  )
  .compact();

This is very similar to the code that’s in the StaticJWTController.fixedBuilder method of the code project.

At this point, it’s worth talking about a few anti-patterns related to JWTs and signing. If you’ve ever seen JWT examples before, you’ve likely encountered one of these signing anti-pattern scenarios:

  1. .signWith(
        SignatureAlgorithm.HS256,
       "secret".getBytes("UTF-8")    
    )
  2. .signWith(
        SignatureAlgorithm.HS256,
        "Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=".getBytes("UTF-8")
    )
  3. .signWith(
        SignatureAlgorithm.HS512,
        TextCodec.BASE64.decode("Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=")
    )

Any of the HS type signature algorithms takes a byte array. It’s convenient for humans to read to take a string and convert it to a byte array.

Anti-pattern 1 above demonstrates this. This is problematic because the secret is weakened by being so short and it’s not a byte array in its native form. So, to keep it readable, we can base64 encode the byte array.

However, anti-pattern 2 above takes the base64 encoded string and converts it directly to a byte array. What should be done is to decode the base64 string back into the original byte array.

Number 3 above demonstrates this. So, why is this one also an anti-pattern? It’s a subtle reason in this case. Notice that the signature algorithm is HS512. The byte array is not the maximum length that HS512 can support, making it a weaker secret than what is possible for that algorithm.

The example code includes a class called SecretService that ensures secrets of the proper strength are used for the given algorithm. At application startup time, a new set of secrets is created for each of the HS algorithms. There are endpoints to refresh the secrets as well as to explicitly set the secrets.

If you have the project running as described above, execute the following so that the JWT examples below match the responses from your project.

http POST localhost:8080/set-secrets \
  HS256="Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=" \
  HS384="VW96zL+tYlrJLNCQ0j6QPTp+d1q75n/Wa8LVvpWyG8pPZOP6AA5X7XOIlI90sDwx" \
  HS512="cd+Pr1js+w2qfT2BoCD+tPcYp9LbjpmhSMEJqUob1mcxZ7+Wmik4AYdjX+DlDjmE4yporzQ9tm7v3z/j+QbdYg=="

Now, you can hit the /static-builder endpoint:

http http://localhost:8080/static-builder

This produces a JWT that looks like this:

eyJhbGciOiJIUzI1NiJ9.
eyJpc3MiOiJTdG9ybXBhdGgiLCJzdWIiOiJtc2lsdmVybWFuIiwibmFtZSI6Ik1pY2FoIFNpbHZlcm1hbiIsInNjb3BlIjoiYWRtaW5zIiwiaWF0IjoxNDY2Nzk2ODIyLCJleHAiOjQ2MjI0NzA0MjJ9.
kP0i_RvTAmI8mgpIkDFhRX3XthSdP-eqqFKGcU92ZIQ

Now, hit:

http http://localhost:8080/parser?jwt=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJzdWIiOiJtc2lsdmVybWFuIiwibmFtZSI6Ik1pY2FoIFNpbHZlcm1hbiIsInNjb3BlIjoiYWRtaW5zIiwiaWF0IjoxNDY2Nzk2ODIyLCJleHAiOjQ2MjI0NzA0MjJ9.kP0i_RvTAmI8mgpIkDFhRX3XthSdP-eqqFKGcU92ZIQ

The response has all the claims that we included when we created the JWT.

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
...
{
    "jws": {
        "body": {
            "exp": 4622470422,
            "iat": 1466796822,
            "iss": "Stormpath",
            "name": "Micah Silverman",
            "scope": "admins",
            "sub": "msilverman"
        },
        "header": {
            "alg": "HS256"
        },
        "signature": "kP0i_RvTAmI8mgpIkDFhRX3XthSdP-eqqFKGcU92ZIQ"
    },
    "status": "SUCCESS"
}

This is the parsing operation, which we’ll get into in the next section.

Now, let’s hit an endpoint that takes claims as parameters and will build a custom JWT for us.

http -v POST localhost:8080/dynamic-builder-general iss=Stormpath sub=msilverman hasMotorcycle:=true

Note: There’s a subtle difference between the hasMotorcycle claim and the other claims. httpie assumes that JSON parameters are strings by default. To submit raw JSON using using httpie, you use the := form rather than =. Without that, it would submit “hasMotorcycle”: “true”, which is not what we want.

Here’s the output:

POST /dynamic-builder-general HTTP/1.1
Accept: application/json
...
{
    "hasMotorcycle": true,
    "iss": "Stormpath",
    "sub": "msilverman"
}

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
...
{
    "jwt": 
      "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJzdWIiOiJtc2lsdmVybWFuIiwiaGFzTW90b3JjeWNsZSI6dHJ1ZX0.OnyDs-zoL3-rw1GaSl_KzZzHK9GoiNocu-YwZ_nQNZU",
    "status": "SUCCESS"
}

Let’s take a look at the code that backs this endpoint:

@RequestMapping(value = "/dynamic-builder-general", method = POST)
public JwtResponse dynamicBuilderGeneric(@RequestBody Map<String, Object> claims) 
  throws UnsupportedEncodingException {
    String jws =  Jwts.builder()
        .setClaims(claims)
        .signWith(
            SignatureAlgorithm.HS256,
            secretService.getHS256SecretBytes()
        )
        .compact();
    return new JwtResponse(jws);
}

Line 2 ensures that the incoming JSON is automatically converted to a Java Map<String, Object>, which is super handy for JJWT as the method on line 5 simply takes that Map and sets all the claims at once.

As terse as this code is, we need something more specific to ensure that the claims that are passed are valid. Using the .setClaims(Map<String, Object> claims) method is handy when you already know that the claims represented in the map are valid. This is where the type-safety of Java comes into the JJWT library.

For each of the Registered Claims defined in the JWT specification, there’s a corresponding Java method in the JJWT that takes the spec-correct type.

Let’s hit another endpoint in our example and see what happens:

http -v POST localhost:8080/dynamic-builder-specific iss=Stormpath sub:=5 hasMotorcycle:=true

Note that we’ve passed in an integer, 5, for the “sub” claim. Here’s the output:

POST /dynamic-builder-specific HTTP/1.1
Accept: application/json
...
{
    "hasMotorcycle": true,
    "iss": "Stormpath",
    "sub": 5
}

HTTP/1.1 400 Bad Request
Connection: close
Content-Type: application/json;charset=UTF-8
...
{
    "exceptionType": "java.lang.ClassCastException",
    "message": "java.lang.Integer cannot be cast to java.lang.String",
    "status": "ERROR"
}

Now, we’re getting an error response because the code is enforcing the type of the Registered Claims. In this case, sub must be a string. Here’s the code that backs this endpoint:

@RequestMapping(value = "/dynamic-builder-specific", method = POST)
public JwtResponse dynamicBuilderSpecific(@RequestBody Map<String, Object> claims) 
  throws UnsupportedEncodingException {
    JwtBuilder builder = Jwts.builder();
    
    claims.forEach((key, value) -> {
        switch (key) {
            case "iss":
                builder.setIssuer((String) value);
                break;
            case "sub":
                builder.setSubject((String) value);
                break;
            case "aud":
                builder.setAudience((String) value);
                break;
            case "exp":
                builder.setExpiration(Date.from(
                    Instant.ofEpochSecond(Long.parseLong(value.toString()))
                ));
                break;
            case "nbf":
                builder.setNotBefore(Date.from(
                    Instant.ofEpochSecond(Long.parseLong(value.toString()))
                ));
                break;
            case "iat":
                builder.setIssuedAt(Date.from(
                    Instant.ofEpochSecond(Long.parseLong(value.toString()))
                ));
                break;
            case "jti":
                builder.setId((String) value);
                break;
            default:
                builder.claim(key, value);
        }
    });
	
    builder.signWith(SignatureAlgorithm.HS256, secretService.getHS256SecretBytes());

    return new JwtResponse(builder.compact());
}

Just like before, the method accepts a Map<String, Object> of claims as its parameter. However, this time, we are calling the specific method for each of the Registered Claims which enforces type.

One refinement to this is to make the error message more specific. Right now, we only know that one of our claims is not the correct type. We don’t know which claim was in error or what it should be. Here’s a method that will give us a more specific error message. It also deals with a bug in the current code.

private void ensureType(String registeredClaim, Object value, Class expectedType) {
    boolean isCorrectType =
        expectedType.isInstance(value) ||
        expectedType == Long.class && value instanceof Integer;

    if (!isCorrectType) {
        String msg = "Expected type: " + expectedType.getCanonicalName() + 
		    " for registered claim: '" + registeredClaim + "', but got value: " + 
			value + " of type: " + value.getClass().getCanonicalName();
        throw new JwtException(msg);
    }
}

Line 3 checks that the passed in value is of the expected type. If not, a JwtException is thrown with the specific error. Let’s take a look at this in action by making the same call we did earlier:

http -v POST localhost:8080/dynamic-builder-specific iss=Stormpath sub:=5 hasMotorcycle:=true
POST /dynamic-builder-specific HTTP/1.1
Accept: application/json
...
User-Agent: HTTPie/0.9.3

{
    "hasMotorcycle": true,
    "iss": "Stormpath",
    "sub": 5
}

HTTP/1.1 400 Bad Request
Connection: close
Content-Type: application/json;charset=UTF-8
...
{
    "exceptionType": "io.jsonwebtoken.JwtException",
    "message": 
      "Expected type: java.lang.String for registered claim: 'sub', but got value: 5 of type: java.lang.Integer",
    "status": "ERROR"
}

Now, we have a very specific error message telling us that the sub claim is the one in error.

Let’s circle back to that bug in our code. The issue has nothing to do with the JJWT library. The issue is that the JSON to Java Object mapper built into Spring Boot is too smart for our own good.

If there’s a method that accepts a Java Object, the JSON mapper will automatically convert a passed in number that is less than or equal to 2,147,483,647 into a Java Integer. Likewise, it will automatically convert a passed in number that is greater than 2,147,483,647 into a Java Long. For the iat, nbf, and exp claims of a JWT, we want our ensureType test to pass whether the mapped Object is an Integer or a Long. That’s why we have the additional clause in determining if the passed in value is the correct type:

 boolean isCorrectType =
     expectedType.isInstance(value) ||
     expectedType == Long.class && value instanceof Integer;

If we’re expecting a Long, but the value is an instance of Integer, we still say it’s the correct type. With an understanding of what’s happening with this validation, we can now integrate it into our dynamicBuilderSpecific method:

@RequestMapping(value = "/dynamic-builder-specific", method = POST)
public JwtResponse dynamicBuilderSpecific(@RequestBody Map<String, Object> claims) 
  throws UnsupportedEncodingException {
    JwtBuilder builder = Jwts.builder();

    claims.forEach((key, value) -> {
        switch (key) {
            case "iss":
                ensureType(key, value, String.class);
                builder.setIssuer((String) value);
                break;
            case "sub":
                ensureType(key, value, String.class);
                builder.setSubject((String) value);
                break;
            case "aud":
                ensureType(key, value, String.class);
                builder.setAudience((String) value);
                break;
            case "exp":
                ensureType(key, value, Long.class);
                builder.setExpiration(Date.from(
				    Instant.ofEpochSecond(Long.parseLong(value.toString()))
				));
                break;
            case "nbf":
                ensureType(key, value, Long.class);
                builder.setNotBefore(Date.from(
					Instant.ofEpochSecond(Long.parseLong(value.toString()))
				));
                break;
            case "iat":
                ensureType(key, value, Long.class);
                builder.setIssuedAt(Date.from(
					Instant.ofEpochSecond(Long.parseLong(value.toString()))
				));
                break;
            case "jti":
                ensureType(key, value, String.class);
                builder.setId((String) value);
                break;
            default:
                builder.claim(key, value);
        }
    });

    builder.signWith(SignatureAlgorithm.HS256, secretService.getHS256SecretBytes());

    return new JwtResponse(builder.compact());
}

Note: In all the example code in this section, JWTs are signed with the HMAC using SHA-256 algorithm. This is to keep the examples simple. The JJWT library supports 12 different signature algorithms that you can take advantage of in your own code.

5. Parsing JWTs with JJWT

We saw earlier that our code example has an endpoint for parsing a JWT. Hitting this endpoint:

http http://localhost:8080/parser?jwt=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJzdWIiOiJtc2lsdmVybWFuIiwibmFtZSI6Ik1pY2FoIFNpbHZlcm1hbiIsInNjb3BlIjoiYWRtaW5zIiwiaWF0IjoxNDY2Nzk2ODIyLCJleHAiOjQ2MjI0NzA0MjJ9.kP0i_RvTAmI8mgpIkDFhRX3XthSdP-eqqFKGcU92ZIQ

produces this response:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
...
{
    "claims": {
        "body": {
            "exp": 4622470422,
            "iat": 1466796822,
            "iss": "Stormpath",
            "name": "Micah Silverman",
            "scope": "admins",
            "sub": "msilverman"
        },
        "header": {
            "alg": "HS256"
        },
        "signature": "kP0i_RvTAmI8mgpIkDFhRX3XthSdP-eqqFKGcU92ZIQ"
    },
    "status": "SUCCESS"
}

The parser method of the StaticJWTController class looks like this:

@RequestMapping(value = "/parser", method = GET)
public JwtResponse parser(@RequestParam String jwt) throws UnsupportedEncodingException {
    Jws<Claims> jws = Jwts.parser()
        .setSigningKeyResolver(secretService.getSigningKeyResolver())
        .parseClaimsJws(jwt);

    return new JwtResponse(jws);
}

Line 4 indicates that we expect the incoming string to be a signed JWT (a JWS). And, we are using the same secret that was used to sign the JWT in parsing it. Line 5 parses the claims from the JWT. Internally, it is verifying the signature and it will throw an exception if the signature is invalid.

Notice that in this case we are passing in a SigningKeyResolver rather than a key itself. This is one of the most powerful aspects of JJWT. The header of JWT indicates the algorithm used to sign it. However, we need to verify the JWT before we trust it. It would seem to be a catch 22. Let’s look at the SecretService.getSigningKeyResolver method:

private SigningKeyResolver signingKeyResolver = new SigningKeyResolverAdapter() {
    @Override
    public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
        return TextCodec.BASE64.decode(secrets.get(header.getAlgorithm()));
    }
};

Using the access to the JwsHeader, I can inspect the algorithm and return the proper byte array for the secret that was used to sign the JWT. Now, JJWT will verify that the JWT has not been tampered with using this byte array as the key.

If I remove the last character of the passed in JWT (which is part of the signature), this is the response:

HTTP/1.1 400 Bad Request
Connection: close
Content-Type: application/json;charset=UTF-8
Date: Mon, 27 Jun 2016 13:19:08 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked

{
    "exceptionType": "io.jsonwebtoken.SignatureException",
    "message": 
      "JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.",
    "status": "ERROR"
}

6. JWTs in Practice: Spring Security CSRF Tokens

While the focus of this post is not Spring Security, we are going to delve into it a bit here to showcase some real-world usage of the JJWT library.

Cross Site Request Forgery is a security vulnerability whereby a malicious website tricks you into submitting requests to a website that you have established trust with. One of the common remedies for this is to implement a synchronizer token pattern. This approach inserts a token into the web form and the application server checks the incoming token against its repository to confirm that it is correct. If the token is missing or invalid, the server will respond with an error.

Spring Security has the synchronizer token pattern built in. Even better, if you are using the Spring Boot and Thymeleaf templates, the synchronizer token is automatically inserted for you.

By default, the token that Spring Security uses is a “dumb” token. It’s just a series of letters and numbers. This approach is just fine and it works. In this section, we enhance the basic functionality by using JWTs as the token. In addition to verifying that the submitted token is the one expected, we validate the JWT to further prove that the token has not been tampered with and to ensure that it is not expired.

To get started, we are going to configure Spring Security using Java configuration. By default, all paths require authentication and all POST endpoints require CSRF tokens. We are going to relax that a bit so that what we’ve built so far still works.

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private String[] ignoreCsrfAntMatchers = {
        "/dynamic-builder-compress",
        "/dynamic-builder-general",
        "/dynamic-builder-specific",
        "/set-secrets"
    };

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
                .ignoringAntMatchers(ignoreCsrfAntMatchers)
            .and().authorizeRequests()
                .antMatchers("/**")
                .permitAll();
    }
}

We are doing two things here. First, we are saying the CSRF tokens are not required when posting to our REST API endpoints (line 15). Second, we are saying that unauthenticated access should be allowed for all paths (lines 17 – 18).

Let’s confirm that Spring Security is working the way we expect. Fire up the app and hit this url in your browser:

http://localhost:8080/jwt-csrf-form

Here’s the Thymeleaf template for this view:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <!--/*/ <th:block th:include="fragments/head :: head"/> /*/-->
    </head>
    <body>
        <div class="container-fluid">
            <div class="row">
                <div class="box col-md-6 col-md-offset-3">
                    <p/>
                    <form method="post" th:action="@{/jwt-csrf-form}">
                        <input type="submit" class="btn btn-primary" value="Click Me!"/>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>

This is a very basic form that will POST to the same endpoint when submitted. Notice that there is no explicit reference to CSRF tokens in the form. If you view the source, you will see something like:

<input type="hidden" name="_csrf" value="5f375db2-4f40-4e72-9907-a290507cb25e" />

This is all the confirmation you need to know that Spring Security is functioning and that the Thymeleaf templates are automatically inserting the CSRF token.

To make the value a JWT, we will enable a custom CsrfTokenRepository. Here’s how our Spring Security configuration changes:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    CsrfTokenRepository jwtCsrfTokenRepository;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
                .csrfTokenRepository(jwtCsrfTokenRepository)
                .ignoringAntMatchers(ignoreCsrfAntMatchers)
            .and().authorizeRequests()
                .antMatchers("/**")
                .permitAll();
    }
}

To connect this, we need a configuration that exposes a bean that returns the custom token repository. Here’s the configuration:

@Configuration
public class CSRFConfig {

    @Autowired
    SecretService secretService;

    @Bean
    @ConditionalOnMissingBean
    public CsrfTokenRepository jwtCsrfTokenRepository() {
        return new JWTCsrfTokenRepository(secretService.getHS256SecretBytes());
    }
}

And, here’s our custom repository (the important bits):

public class JWTCsrfTokenRepository implements CsrfTokenRepository {

    private static final Logger log = LoggerFactory.getLogger(JWTCsrfTokenRepository.class);
    private byte[] secret;

    public JWTCsrfTokenRepository(byte[] secret) {
        this.secret = secret;
    }

    @Override
    public CsrfToken generateToken(HttpServletRequest request) {
        String id = UUID.randomUUID().toString().replace("-", "");

        Date now = new Date();
        Date exp = new Date(System.currentTimeMillis() + (1000*30)); // 30 seconds

        String token;
        try {
            token = Jwts.builder()
                .setId(id)
                .setIssuedAt(now)
                .setNotBefore(now)
                .setExpiration(exp)
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
        } catch (UnsupportedEncodingException e) {
            log.error("Unable to create CSRf JWT: {}", e.getMessage(), e);
            token = id;
        }

        return new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", token);
    }

    @Override
    public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
        ...
    }

    @Override
    public CsrfToken loadToken(HttpServletRequest request) {
        ...
    }
}

The generateToken method creates a JWT that expires 30 seconds after it’s created. With this plumbing in place, we can fire up the application again and look at the source of /jwt-csrf-form.

Now, the hidden field looks like this:

<input type="hidden" name="_csrf" 
  value="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxZjIyMDdiNTVjOWM0MjU0YjZlMjY4MjQwYjIwNzZkMSIsImlhdCI6MTQ2NzA3MDQwMCwibmJmIjoxNDY3MDcwNDAwLCJleHAiOjE0NjcwNzA0MzB9.2kYLO0iMWUheAncXAzm0UdQC1xUC5I6RI_ShJ_74e5o" />

Huzzah! Now our CSRF token is a JWT. That wasn’t too hard.

However, this is only half the puzzle. By default, Spring Security simply saves the CSRF token and confirms that the token submitted in a web form matches the one that’s saved. We want to extend the functionality to validate the JWT and make sure it hasn’t expired. To do that, we’ll add in a filter. Here’s what our Spring Security configuration looks like now:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    ...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .addFilterAfter(new JwtCsrfValidatorFilter(), CsrfFilter.class)
            .csrf()
                .csrfTokenRepository(jwtCsrfTokenRepository)
                .ignoringAntMatchers(ignoreCsrfAntMatchers)
            .and().authorizeRequests()
                .antMatchers("/**")
                .permitAll();
    }

    ...
}

On line 9, we’ve added in a filter and we are placing it in the filter chain after the default CsrfFilter. So, by the time our filter is hit, the JWT token (as a whole) will have already been confirmed to be the correct value saved by Spring Security.

Here’s the JwtCsrfValidatorFilter (it’s private as it’s an inner class of our Spring Security configuration):

private class JwtCsrfValidatorFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(
      HttpServletRequest request, 
      HttpServletResponse response, 
      FilterChain filterChain) throws ServletException, IOException {
        // NOTE: A real implementation should have a nonce cache so the token cannot be reused
        CsrfToken token = (CsrfToken) request.getAttribute("_csrf");

        if (
            // only care if it's a POST
            "POST".equals(request.getMethod()) &&
            // ignore if the request path is in our list
            Arrays.binarySearch(ignoreCsrfAntMatchers, request.getServletPath()) < 0 &&
            // make sure we have a token
            token != null
        ) {
            // CsrfFilter already made sure the token matched. 
            // Here, we'll make sure it's not expired
            try {
                Jwts.parser()
                    .setSigningKey(secret.getBytes("UTF-8"))
                    .parseClaimsJws(token.getToken());
            } catch (JwtException e) {
                // most likely an ExpiredJwtException, but this will handle any
                request.setAttribute("exception", e);
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                RequestDispatcher dispatcher = request.getRequestDispatcher("expired-jwt");
                dispatcher.forward(request, response);
            }
        }

        filterChain.doFilter(request, response);
    }
}

Take a look at line 23 on. We are parsing the JWT as before. In this case, if an Exception is thrown, the request is forwarded to the expired-jwt template. If the JWT validates, then processing continues as normal.

This closes the loop on overriding the default Spring Security CSRF token behavior with a JWT token repository and validator.

If you fire up the app, browse to /jwt-csrf-form, wait a little more than 30 seconds and click the button, you will see something like this:

jwt_expired

7. JJWT Extended Features

We’ll close out our JJWT journey with a word on some of the features that extend beyond the specification.

7.1. Enforce Claims

As part of the parsing process, JJWT allows you to specify required claims and values those claims should have. This is very handy if there is certain information in your JWTs that must be present in order for you to consider them valid. It avoids a lot of branching logic to manually validate claims. Here’s the method that serves the /parser-enforce endpoint of our sample project.

@RequestMapping(value = "/parser-enforce", method = GET)
public JwtResponse parserEnforce(@RequestParam String jwt) 
  throws UnsupportedEncodingException {
    Jws<Claims> jws = Jwts.parser()
        .requireIssuer("Stormpath")
        .require("hasMotorcycle", true)
        .setSigningKeyResolver(secretService.getSigningKeyResolver())
        .parseClaimsJws(jwt);

    return new JwtResponse(jws);
}

Lines 5 and 6 show you the syntax for registered claims as well as custom claims. In this example, the JWT will be considered invalid if the iss claim is not present or does not have the value: Stormpath. It will also be invalid if the custom hasMotorcycle claim is not present or does not have the value: true.

Let’s first create a JWT that follows the happy path:

http -v POST localhost:8080/dynamic-builder-specific \
  iss=Stormpath hasMotorcycle:=true sub=msilverman
POST /dynamic-builder-specific HTTP/1.1
Accept: application/json
...
{
    "hasMotorcycle": true,
    "iss": "Stormpath",
    "sub": "msilverman"
}

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
...
{
    "jwt": 
      "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJoYXNNb3RvcmN5Y2xlIjp0cnVlLCJzdWIiOiJtc2lsdmVybWFuIn0.qrH-U6TLSVlHkZdYuqPRDtgKNr1RilFYQJtJbcgwhR0",
    "status": "SUCCESS"
}

Now, let’s validate that JWT:

http -v localhost:8080/parser-enforce?jwt=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJoYXNNb3RvcmN5Y2xlIjp0cnVlLCJzdWIiOiJtc2lsdmVybWFuIn0.qrH-U6TLSVlHkZdYuqPRDtgKNr1RilFYQJtJbcgwhR0
GET /parser-enforce?jwt=http 
  -v localhost:8080/parser-enforce?jwt=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJoYXNNb3RvcmN5Y2xlIjp0cnVlLCJzdWIiOiJtc2lsdmVybWFuIn0.qrH-U6TLSVlHkZdYuqPRDtgKNr1RilFYQJtJbcgwhR0 HTTP/1.1
Accept: */*
...
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
...
{
    "jws": {
        "body": {
            "hasMotorcycle": true,
            "iss": "Stormpath",
            "sub": "msilverman"
        },
        "header": {
            "alg": "HS256"
        },
        "signature": "qrH-U6TLSVlHkZdYuqPRDtgKNr1RilFYQJtJbcgwhR0"
    },
    "status": "SUCCESS"
}

So far, so good. Now, this time, let’s leave the hasMotorcycle out:

http -v POST localhost:8080/dynamic-builder-specific iss=Stormpath sub=msilverman

This time, if we try to validate the JWT:

http -v localhost:8080/parser-enforce?jwt=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJzdWIiOiJtc2lsdmVybWFuIn0.YMONlFM1tNgttUYukDRsi9gKIocxdGAOLaJBymaQAWc

we get:

GET /parser-enforce?jwt=http -v localhost:8080/parser-enforce?jwt=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJzdWIiOiJtc2lsdmVybWFuIn0.YMONlFM1tNgttUYukDRsi9gKIocxdGAOLaJBymaQAWc HTTP/1.1
Accept: */*
...
HTTP/1.1 400 Bad Request
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: close
Content-Type: application/json;charset=UTF-8
...
{
    "exceptionType": "io.jsonwebtoken.MissingClaimException",
    "message": 
      "Expected hasMotorcycle claim to be: true, but was not present in the JWT claims.",
    "status": "ERROR"
}

This indicates that our hasMotorcycle claim was expected, but was missing.

Let’s do one more example:

http -v POST localhost:8080/dynamic-builder-specific iss=Stormpath hasMotorcycle:=false sub=msilverman

This time, the required claim is present, but it has the wrong value. Let’s see the output of:

http -v localhost:8080/parser-enforce?jwt=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJoYXNNb3RvcmN5Y2xlIjpmYWxzZSwic3ViIjoibXNpbHZlcm1hbiJ9.8LBq2f0eINB34AzhVEgsln_KDo-IyeM8kc-dTzSCr0c
GET /parser-enforce?jwt=http 
  -v localhost:8080/parser-enforce?jwt=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJoYXNNb3RvcmN5Y2xlIjpmYWxzZSwic3ViIjoibXNpbHZlcm1hbiJ9.8LBq2f0eINB34AzhVEgsln_KDo-IyeM8kc-dTzSCr0c HTTP/1.1
Accept: */*
...
HTTP/1.1 400 Bad Request
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: close
Content-Type: application/json;charset=UTF-8
...
{
    "exceptionType": "io.jsonwebtoken.IncorrectClaimException",
    "message": "Expected hasMotorcycle claim to be: true, but was: false.",
    "status": "ERROR"
}

This indicates that our hasMotorcycle claim was present, but had a value that was not expected.

MissingClaimException and IncorrectClaimException are your friends when enforcing claims in your JWTs and a feature that only the JJWT library has.

7.2. JWT Compression

If you have a lot of claims on a JWT, it can get big – so big, that it might not fit in a GET url in some browsers.

Let’s a make a big JWT:

http -v POST localhost:8080/dynamic-builder-specific \
  iss=Stormpath hasMotorcycle:=true sub=msilverman the=quick brown=fox jumped=over lazy=dog \
  somewhere=over rainbow=way up=high and=the dreams=you dreamed=of

Here’s the JWT that produces:

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdG9ybXBhdGgiLCJoYXNNb3RvcmN5Y2xlIjp0cnVlLCJzdWIiOiJtc2lsdmVybWFuIiwidGhlIjoicXVpY2siLCJicm93biI6ImZveCIsImp1bXBlZCI6Im92ZXIiLCJsYXp5IjoiZG9nIiwic29tZXdoZXJlIjoib3ZlciIsInJhaW5ib3ciOiJ3YXkiLCJ1cCI6ImhpZ2giLCJhbmQiOiJ0aGUiLCJkcmVhbXMiOiJ5b3UiLCJkcmVhbWVkIjoib2YifQ.AHNJxSTiDw_bWNXcuh-LtPLvSjJqwDvOOUcmkk7CyZA

That sucker’s big! Now, let’s hit a slightly different endpoint with the same claims:

http -v POST localhost:8080/dynamic-builder-compress \
  iss=Stormpath hasMotorcycle:=true sub=msilverman the=quick brown=fox jumped=over lazy=dog \
  somewhere=over rainbow=way up=high and=the dreams=you dreamed=of

This time, we get:

eyJhbGciOiJIUzI1NiIsImNhbGciOiJERUYifQ.eNpEzkESwjAIBdC7sO4JegdXnoC2tIk2oZLEGB3v7s84jjse_AFe5FOikc5ZLRycHQ3kOJ0Untu8C43ZigyUyoRYSH6_iwWOyGWHKd2Kn6_QZFojvOoDupRwyAIq4vDOzwYtugFJg1QnJv-5sY-TVjQqN7gcKJ3f-j8c-6J-baDFhEN_uGn58XtnpfcHAAD__w.3_wc-2skFBbInk0YAQ96yGWwr8r1xVdbHn-uGPTFuFE

62 characters shorter! Here’s the code for the method used to generate the JWT:

@RequestMapping(value = "/dynamic-builder-compress", method = POST)
public JwtResponse dynamicBuildercompress(@RequestBody Map<String, Object> claims) 
  throws UnsupportedEncodingException {
    String jws =  Jwts.builder()
        .setClaims(claims)
        .compressWith(CompressionCodecs.DEFLATE)
        .signWith(
            SignatureAlgorithm.HS256,
            secretService.getHS256SecretBytes()
        )
        .compact();
    return new JwtResponse(jws);
}

Notice on line 6 we are specifying  a compression algorithm to use. That’s all there is to it.

What about parsing compressed JWTs? The JJWT library automatically detects the compression and uses the same algorithm to decompress:

GET /parser?jwt=eyJhbGciOiJIUzI1NiIsImNhbGciOiJERUYifQ.eNpEzkESwjAIBdC7sO4JegdXnoC2tIk2oZLEGB3v7s84jjse_AFe5FOikc5ZLRycHQ3kOJ0Untu8C43ZigyUyoRYSH6_iwWOyGWHKd2Kn6_QZFojvOoDupRwyAIq4vDOzwYtugFJg1QnJv-5sY-TVjQqN7gcKJ3f-j8c-6J-baDFhEN_uGn58XtnpfcHAAD__w.3_wc-2skFBbInk0YAQ96yGWwr8r1xVdbHn-uGPTFuFE HTTP/1.1
Accept: */*
...
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
...
{
    "claims": {
        "body": {
            "and": "the",
            "brown": "fox",
            "dreamed": "of",
            "dreams": "you",
            "hasMotorcycle": true,
            "iss": "Stormpath",
            "jumped": "over",
            "lazy": "dog",
            "rainbow": "way",
            "somewhere": "over",
            "sub": "msilverman",
            "the": "quick",
            "up": "high"
        },
        "header": {
            "alg": "HS256",
            "calg": "DEF"
        },
        "signature": "3_wc-2skFBbInk0YAQ96yGWwr8r1xVdbHn-uGPTFuFE"
    },
    "status": "SUCCESS"
}

Notice the calg claim in the header. This was automatically encoded into the JWT and it provides the hint to the parser about what algorithm to use for decompression.

NOTE: The JWE specification does support compression. In an upcoming release of the JJWT library, we will support JWE and compressed JWEs. We will continue to support compression in other types of JWTs, even though it is not specified.

8. Token Tools for Java Devs

While the core focus of this article was not Spring Boot or Spring Security, using those two technologies made it easy to demonstrate all the features discussed in this article. You should be able to build in fire up the server and start playing with the various endpoints we’ve discussed. Just hit:

http http://localhost:8080

Stormpath is also excited to bring a number of open source developer tools to the Java community. These include:

8.1. JJWT (What we’ve been talking about)

JJWT is an easy to use tool for developers to create and verify JWTs in Java. Like many libraries Stormpath supports, JJWT is completely free and open source (Apache License, Version 2.0), so everyone can see what it does and how it does it. Do not hesitate to report any issues, suggest improvements, and even submit some code!

8.2. jsonwebtoken.io and java.jsonwebtoken.io

jsonwebtoken.io is a developer tool we created to make it easy to decode JWTs. Simply paste an existing JWT into the appropriate field to decode its header, payload, and signature. jsonwebtoken.io is powered by nJWT, the cleanest free and open source (Apache License, Version 2.0) JWT library for Node.js developers. You can also see code generated for a variety of languages at this website. The website itself is open-source and can be found here.

java.jsonwebtoken.io is specifically for the JJWT library. You can alter the headers and payload in the upper right box, see the JWT generated by JJWT in the upper left box, and see a sample of the builder and parser Java code in the lower boxes. The website itself is open source and can be found here.

8.3. JWT Inspector

The new kid on the block, JWT Inspector is an open source Chrome extension that allows developers to inspect and debug JWTs directly in-browser. The JWT Inspector will discover JWTs on your site (in cookies, local/session storage, and headers) and make them easily accessible through your navigation bar and DevTools panel.

9. JWT This Down!

JWTs add some intelligence to ordinary tokens. The ability to cryptographically sign and verify, build in expiration times and encode other information into JWTs sets the stage for truly stateless session management. This has a big impact on the ability to scale applications.

At Stormpath, we use JWTs for OAuth2 tokens, CSRF tokens and assertions between microservices, among other usages.

Once you start using JWTs, you may never go back to the dumb tokens of the past. Have any questions? Hit me up at @afitnerd on twitter.

Intro to the Jackson ObjectMapper

$
0
0

I usually post about Jackson and JSON stuff on Twitter - you can follow me there:

1. Overview

This writeup is focused on understanding the Jackson ObjectMapper class – and how to serialize Java objects into JSON and deserialize JSON string into Java objects. To understand more about Jackson library in general, the Jackson Tutorial is a good place to start.

2. Dependencies

Let’s first add the following dependencies to pom.xml:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.7.5</version>
</dependency>

This dependency will transitively add the following libraries to the classpath:

  1. jackson-annotations-2.7.5.jar
  2. jackson-core-2.7.5.jar
  3. jackson-databind-2.7.5.jar

Always use the latest versions as seen the maven central repository for Jackson databind.

3. Reading and Writing Using ObjectMapper

Let’s start with the basic read and write operations.

The simple readValue API of the ObjectMapper is a good entry-point; this can be used to parse or deserialize JSON content into a Java object.

On the write side of things – the writeValue API can be used to serialize any Java object as JSON output.

We’ll use the following Car class with two fields as the object to serialize or deserialize throughout this article:

public class Car {

    private String color;
    private String type;

    // standard getters setters
}

3.1. Java Object to JSON

A simple example of serialization of Java Object into JSON using the writeValue method of ObjectMapper class:

ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("yellow", "renault");
objectMapper.writeValue(new File("target/car.json"), car);

Output of the above can be seen in the file as following:

{"color":"yellow","type":"renault"}

The methods writeValueAsString and writeValueAsBytes of ObjectMapper class, generates a JSON from a Java object and returns the generated JSON as a string or as a byte array:

String carAsString = objectMapper.writeValueAsString(car);

3.2. JSON to Java Object

Below is a simple example of JSON string converted to Java object using the ObjectMapper class:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Car car = objectMapper.readValue(json, Car.class);	

The readValue function also accepts other forms of input like a file containing JSON string:

Car car = objectMapper.readValue(new File("target/json_car.json"), Car.class);

or a URL:

Car car = objectMapper.readValue(new URL("target/json_car.json"), Car.class);

3.3. JSON to Jackson JsonNode

Alternatively a JSON can be parsed into a JsonNode object and used to retrieve data from a given specific node:

String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";
JsonNode jsonNode = objectMapper.readTree(json);
String color = jsonNode.get("color").asText();
// Output: color -> Black

3.4. Creating Java List from JSON Array String

A JSON in the form of array can be parsed into a Java object list by parsing in the following way:

String jsonCarArray = 
  "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});

3.5. Creating Java Map from JSON String

A JSON in the form of string can be parsed into a Java Map object by parsing in the following way:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Map<String, Object> map = objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){});

4. Advanced Features

One of the greatest strength of the Jackson library is the highly customizable serialization and deserialization process.

In this section we will go through some advanced features where the input or the output JSON response can be different from the object which generates or consumes the response.

4.1. Configuring Serialization or Deserialization Feature

While converting JSON objects to Java classes, in case the JSON string has some new fields, then the default process will run in exception:

String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }";

The JSON string in the above example in the default parsing process to the Java object for the Class Car will result in the UnrecognizedPropertyException  exception.

Through the configure method we can extend the default process to ignore the new fields:

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Car car = objectMapper.readValue(jsonString, Car.class);

JsonNode jsonNodeRoot = objectMapper.readTree(jsonString);
JsonNode jsonNodeYear = jsonNodeRoot.get("year");
String year = jsonNodeYear.asText();

Yet another option is based on the FAIL_ON_NULL_FOR_PRIMITIVES which defines if the null values for primitive values are allowed: 

objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);

Similarly, FAIL_ON_NUMBERS_FOR_ENUM controls if enum values are allowed to be serialized/deserialized as numbers 

objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);

You can find the comprehensive list of serialization and deserialization features on the official site.

4.2. Creating Custom Serializer or Deserializer

Another very important feature of ObjectMapper class is the ability to register custom serializer and deserializer. Custom serializer and deserializer are very useful in situations where the input or the output JSON response is different in structure than the Java class into which it must be serialized or deserialized.

Below is an example of custom JSON serializer:

public class CustomCarSerializer extends JsonSerializer<Car> {
    public CustomCarSerializer() { }
    @Override
    public void serialize(Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("car_brand", car.getType());
        jsonGenerator.writeEndObject();
    }
}

This custom serializer can be invoked like this:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = 
  new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null));
module.addSerializer(Car.class, new CustomCarSerializer());
mapper.registerModule(module);
Car car = new Car("yellow", "renault");
String carJson = mapper.writeValueAsString(car);

Here’s what the Car looks like (as JSON output) on the client side:

var carJson = {"car_brand":"renault"}

And here’s an example of a custom JSON deserializer:

public class CustomCarDeserializer extends JsonDeserializer<Car> {
    public CustomCarDeserializer() { }
    @Override
    public Car deserialize(JsonParser parser, DeserializationContext deserializer) {
        Car car = new Car();
        ObjectCodec codec = parser.getCodec();
        JsonNode node = codec.readTree(parser);
        
        // try catch block
        JsonNode colorNode = node.get("color");
        String color = colorNode.asText();
        car.setColor(color);
        return car;
    }
}

This custom deserializer can be invoked in the following way:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
ObjectMapper mapper = new ObjectMapper();
SimpleModule module =
  new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null));
module.addDeserializer(Car.class, new CustomeCarDeserializer());
mapper.registerModule(module);
Car car = mapper.readValue(json, Car.class);

4.3. Handling Date Formats

The default serialization of java.util.Date produces a number i.e. epoch timestamp (number of milliseconds since January 1st, 1970, UTC). But this is not very human readable and further conversion is needed to display human readable format.

Let us wrap the Car instance we used so far inside the Request class with the datePurchased property:

public class Request 
{
    private Car car;
    private Date datePurchased;

    // standard getters setters
}

To control the String format of a date, and set it to e.g. yyyy-MM-dd HH:mm a z, consider the following snippet:

ObjectMapper objectMapper = new ObjectMapper();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
objectMapper.setDateFormat(df);
String carAsString = objectMapper.writeValueAsString(request);
// output: {"car":{"color":"yellow","type":"renault"},"datePurchased":"2016-07-03 11:43 AM CEST"}

To learn more about serializing dates with Jackson, read our more in-depth writeup.

4.4. Handling Collections

Another small but useful feature available through DeserializationFeature is the ability to generate the type of collection desired from a JSON Array response, e.g. as an array:

String jsonCarArray = 
  "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);
// print cars

Or as a List:

String jsonCarArray = 
  "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});
// print cars

More about handling collections with Jackson is available here.

5. Conclusion

Jackson ObjectMapper is a solid and mature JSON serialization/deserialization library for Java. And the ObjectMapper API provide a very simple way to parse and generate JSON response objects with a lot of flexibility.

The article discuss the main features which make the library so popular. The source code that accompanies the article can be found in GitHub.

I usually post about Jackson and JSON stuff on Twitter - you should follow me there:


A Guide to JMockit Expectations

$
0
0

1. Intro

This article is the second installment in the JMockit series. You may want to read the first article as we are assuming that you are already familiar with JMockit’s basics.

Today we’ll go deeper and focus on expectations. We will show how to define more specific or generic argument matching and more advanced ways of defining values.

2. Argument Values Matching 

The following approaches apply both to Expectations as well as Verifications.

2.1. “Any” Fields

JMockit offers a set of utility fields for making argument matching more generic. One of these utilities are the anyX fields.

These will check that any value was passed and there is one for each primitive type (and the corresponding wrapper class), one for strings, and a “universal” one of type Object.

Let’s see an example:

public interface ExpectationsCollaborator {
    String methodForAny1(String s, int i, Boolean b);
    void methodForAny2(Long l, List<String> lst);
}

@Test
public void test(@Mocked ExpectationsCollaborator mock) throws Exception {
    new Expectations() {{
        mock.methodForAny1(anyString, anyInt, anyBoolean); 
        result = "any";
    }};

    Assert.assertEquals("any", mock.methodForAny1("barfooxyz", 0, Boolean.FALSE));
    mock.methodForAny2(2L, new ArrayList<>());

    new FullVerifications() {{
        mock.methodForAny2(anyLong, (List<String>) any);
    }};
}

You must take into account that when using the any field, you need to cast it to the expected type. The complete list of fields is present in the documentation.

2.2. “With” Methods

JMockit also provides several methods to help with generic argument matching. Those are the withX methods.

These allow for a little more advanced matching than the anyX fields. We can see an example here in which we’ll define an expectation for a method that will be triggered with a string containing foo, an integer not equal to 1, a non-null Boolean and any instance of the List class:

public interface ExpectationsCollaborator {
    String methodForWith1(String s, int i);
    void methodForWith2(Boolean b, List<String> l);
}

@Test
public void testForWith(@Mocked ExpectationsCollaborator mock) throws Exception {
    new Expectations() {{
        mock.methodForWith1(withSubstring("foo"), withNotEqual(1));
        result = "with";
    }};

    assertEquals("with", mock.methodForWith1("barfooxyz", 2));
    mock.methodForWith2(Boolean.TRUE, new ArrayList<>());

    new Verifications() {{
        mock.methodForWith2(withNotNull(), withInstanceOf(List.class));
    }};
}

You can see the complete list of withX methods on JMockit’s documentation.

Take into account that the special with(Delegate) and withArgThat(Matcher) will be covered in their own subsection.

2.3. Null Is Not Null

Something that is good to understand sooner than later is that null is not used to define an argument for which null has been passed to a mock.

Actually, null is used as syntactic sugar to define that any object will be passed (so it can only be used for parameters of reference type). To specifically verify that a given parameter receives the null reference, the withNull() matcher can be used.

For the next example, we’ll define the behaviour for a mock, that should be triggered when the arguments passed are: any string, any List, and a null reference:

public interface ExpectationsCollaborator {
    String methodForNulls1(String s, List<String> l);
    void methodForNulls2(String s, List<String> l);
}

@Test
public void testWithNulls(@Mocked ExpectationsCollaborator mock){
    new Expectations() {{
        mock.methodForNulls1(anyString, null); 
        result = "null";
    }};
    
    assertEquals("null", mock.methodForNulls1("blablabla", new ArrayList<String>()));
    mock.methodForNulls2("blablabla", null);
    
    new Verifications() {{
        mock.methodForNulls2(anyString, (List<String>) withNull());
    }};
}

Note the difference: null means any list and withNull() means a null reference to a list. In particular, this avoids the need to cast the value to the declared parameter type (see that the third argument had to be cast but not the second one).

The only condition to be able to use this is that at least one explicit argument matcher had been used for the expectation (either a with method or an any field).

2.4. “Times” Field

Sometimes, we want to constrain the number of invocations expected for a mocked method. For this, JMockit has the reserved words times, minTimes and maxTimes (all three allow non-negative integers only).

public interface ExpectationsCollaborator {
    void methodForTimes1();
    void methodForTimes2();
    void methodForTimes3();
}

@Test
public void testWithTimes(@Mocked ExpectationsCollaborator mock) {
    new Expectations() {{
        mock.methodForTimes1(); times = 2;
        mock.methodForTimes2();
    }};
    
    mock.methodForTimes1();
    mock.methodForTimes1();
    mock.methodForTimes2();
    mock.methodForTimes3();
    mock.methodForTimes3();
    mock.methodForTimes3();
    
    new Verifications() {{
        mock.methodForTimes3(); minTimes = 1; maxTimes = 3;
    }};
}

In this example, we’ve defined that exactly two invocations (not one, not three, exactly two) of methodForTimes1() should be done using the line times = 2;.

Then we used the default behavior (if no repetition constraint is given minTimes = 1; is used) to define that at least one invocation will be done to methodForTimes2().

Lastly, using minTimes = 1; followed by maxTimes = 3; we defined that between one and three invocations would occur to methodForTimes3().

Take into account that both minTimes and maxTimes can be specified for the same expectation, as long as minTimes is assigned first. On the other hand, times can only be used alone.

2.5. Custom Argument Matching

Sometimes argument matching is not as direct as simply specifying a value or using some of the predefined utilities (anyX or withX).

For that cases, JMockit relies on Hamcrest‘s Matcher interface. You just need to define a matcher for the specific testing scenario and use that matcher with a withArgThat() call.

Let’s see an example for matching a specific class to a passed object:

public interface ExpectationsCollaborator {
    void methodForArgThat(Object o);
}

public class Model {
    public String getInfo(){
        return "info";
    }
}

@Test
public void testCustomArgumentMatching(@Mocked ExpectationsCollaborator mock) {
    new Expectations() {{
        mock.methodForArgThat(withArgThat(new BaseMatcher<Object>() {
            @Override
            public boolean matches(Object item) {
                return item instanceof Model && "info".equals(((Model) item).getInfo());
            }

            @Override
            public void describeTo(Description description) { }
        }));
    }};
    mock.methodForArgThat(new Model());
}

3. Returning Values

Let’s now look at the return values; keep in mind that following approaches apply only to Expectations as no return values can be defined for Verifications.

3.1. Result and Returns (…)

When using JMockit, you have three different ways of defining the expected result of the invocation of a mocked method. Of all three, we’ll talk now about the first two (the simplest ones) which will surely cover 90% of everyday use cases.

These two are the result field and the returns(Object…) method:

  • With the result field, you can define one return value for any non-void returning mocked method. This return value can also be an exception to be thrown (this time working for both non-void and void returning methods).
    • Several result field assignations can be done in order to return more than one value for more than one method invocations (you can mix both return values and errors to be thrown).
    • The same behaviour will be achieved when assigning to result a list or an array of values (of the same type than the return type of the mocked method, NO exceptions here).
  • The returns(Object…) method is syntactic sugar for returning several values of the same time.

This is more easily shown with a code snippet:

public interface ExpectationsCollaborator{
    String methodReturnsString();
    int methodReturnsInt();
}

@Test
public void testResultAndReturns(@Mocked Foo mock){
    new StrictExpectations() {{
        mock.methodReturnsString();
        result = "foo";
        result = new Exception();
        result = "bar";
        mock.methodReturnsInt(); result = new int[] { 1, 2, 3 };
        mock.methodReturnsString(); returns("foo", "bar");
        mock.methodReturnsInt(); result = 1;
    }};
    
    assertEquals("Should return foo", "foo", mock.methodReturnsString());
    try {
        mock.methodReturnsString();
    } catch (Exception e) { }
    
    assertEquals("Should return bar", "bar", mock.methodReturnsString());
    assertEquals("Should return 1", 1, mock.methodReturnsInt());
    assertEquals("Should return 2", 2, mock.methodReturnsInt());
    assertEquals("Should return 3", 3, mock.methodReturnsInt());
    assertEquals("Should return foo", "foo", mock.methodReturnsString());
    assertEquals("Should return bar", "bar", mock.methodReturnsString());
    assertEquals("Should return 1", 1, mock.methodReturnsInt());
}

In this example, we have defined that for the first three calls to methodReturnsString() the expected returns are (in order) “foo”, an exception and “bar”. We achieved this using three different assignations to the result field.

Then on line 14, we defined that for the fourth and fifth calls, “foo” and “bar” should be returned using the returns(Object…) method.

For the methodReturnsInt() we defined on line 13 to return 1, 2 and lastly 3 by assigning an array with the different results to the result field and on line 15 we defined to return 1 by a simple assignation to the result field.

As you can see there are several ways of defining return values for mocked methods.

3.2. Delegators

To end the article we’re going to cover the third way of defining the return value: the Delegate interface. This interface is used for defining more complex return values when defining mocked methods.

We’re going to see an example to simply the explaining:

public interface ExpectationsCollaborator {
    Object methodForDelegate(int i);
}

@Test
public void testDelegate(@Mocked ExpectationsCollaborator mock) {
    new Expectations() {{
        
        mock.methodForDelegate(anyInt);
        result = new Delegate() {
            public int delegate(int i) throws Exception {
                if(i < 3) {
                    return 5;
                } else {
                    throw new Exception();
                }
            }
        };
    }};
    
    assertEquals("Should return 5", 5, mock.methodForDelegate(1));
    try {
        mock.methodForDelegate(3);
    } catch (Exception e) { }
}

The way to use a delegator is to create a new instance for it and assign it to a returns field. In this new instance, you should create a new method with the same parameters and return type than the mocked method (you can use any name for it). Inside this new method, use whatever implementation you want in order to return the desired value.

In the example, we did an implementation in which 5 should be returned when the value passed to the mocked method is less than 3 and an exception is thrown otherwise (note that we had to use times = 2; so that the second invocation is expected as we lost the default behaviour by defining a return value).

It may seem like quite a lot of code, but for same cases, it’ll be the only way to achieve the result we want.

4. Conclusion

With this, we practically showed everything we need to create expectations and verifications for our everyday tests.

We’ll of course publish more articles on JMockit, so stay tuned to learn even more.

And, as always, the full implementation of this tutorial can be found on the GitHub project.

4.1. Articles in the Series

All articles of the series:


Circular Dependencies in Spring

$
0
0

1 day left to the Master Class of "Learn Spring Security":

>> CHECK OUT THE COURSE

1. What Is a Circular Dependency?

It happens when a bean A depends on another bean B, and the bean B depends on the bean A as well:

Bean A → Bean B → Bean A

Of course, we could have more beans implied:

Bean A → Bean B → Bean C → Bean D → Bean E → Bean A

2. What Happens in Spring

When Spring context is loading all the beans, it tries to create beans in the order needed for them to work completely. For instance, if we didn’t have a circular dependency, like the following case:

Bean A → Bean B → Bean C

Spring will create bean C, then create bean B (and inject bean C into it), then create bean A (and inject bean B into it).

But, when having a circular dependency, Spring cannot decide which of the beans should be created first, since they depend on one another. In these cases, Spring will raise a BeanCurrentlyInCreationException while loading context.

It can happen in Spring when using constructor injection; if you use other types of injections you should not find this problem since the dependencies will be injected when they are needed and not on the context loading.

3. A Quick Example

Let’s define two beans that depend on one another (via constructor injection):

@Component
public class CircularDependencyA {

    private CircularDependencyB circB;

    @Autowired
    public CircularDependencyA(CircularDependencyB circB) {
        this.circB = circB;
    }
}
@Component
public class CircularDependencyB {

    private CircularDependencyA circA;

    @Autowired
    public CircularDependencyB(CircularDependencyA circA) {
        this.circA = circA;
    }
}

Now we can write a Configuration class for the tests, let’s call it TestConfig, that specifies the base package to scan for components. Let’s assume our beans are defined in package “com.baeldung.circulardependency”:

@Configuration
@ComponentScan(basePackages = { "com.baeldung.circulardependency" })
public class TestConfig {
}

And finally we can write a JUnit test to check the circular dependency. The test can be empty, since the circular dependency will be detected during the context loading.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
public class CircularDependencyTest {

    @Test
    public void givenCircularDependency_whenConstructorInjection_thenItFails() {
        // Empty test; we just want the context to load
    }
}

If you try to run this test, you will get the following exception:

BeanCurrentlyInCreationException: Error creating bean with name 'circularDependencyA':
Requested bean is currently in creation: Is there an unresolvable circular reference?

4. The Workarounds

We will show some of the most popular ways to deal with this problem.

4.1. Redesign

When you have a circular dependency, it’s likely you have a design problem and the responsibilities are not well separated. You should try to redesign the components properly so their hierarchy is well designed and there is no need for circular dependencies.

If you cannot redesign the components (there can be many possible reasons for that: legacy code, code that has already been tested and cannot be modified, not enough time or resources for a complete redesign…), there are some workarounds to try.

4.2. Use @Lazy

A simple way to break the cycle is saying Spring to initialize one of the beans lazily. That is: instead of fully initializing the bean, it will create a proxy to inject it into the other bean. The injected bean will only be fully created when it’s first needed.

To try this with our code, you can change the CircularDependencyA to the following:

@Component
public class CircularDependencyA {

    private CircularDependencyB circB;

    @Autowired
    public CircularDependencyA(@Lazy CircularDependencyB circB) {
        this.circB = circB;
    }
}

If you run the test now, you will see that the error does not happen this time.

4.3. Use Setter Injection

One of the most popular workarounds, and also what Spring documentation proposes, is using setter injections. You can try changing the constructor injectors for setter injectors. This way Spring creates the beans, but the dependencies are not injected until they are needed.

We will change our classes to use setter injections and will add another field (message) to CircularDependencyB so we can make a proper unit test:

@Component
public class CircularDependencyA {

    private CircularDependencyB circB;

    @Autowired
    public void setCircB(CircularDependencyB circB) {
        this.circB = circB;
    }

    public CircularDependencyB getCircB() {
        return circB;
    }
}
@Component
public class CircularDependencyB {

    private CircularDependencyA circA;

    private String message = "Hi!";

    @Autowired
    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }

    public String getMessage() {
        return message;
    }
}

Now we have to make some changes to our unit test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
public class CircularDependencyTest {

    @Autowired
    ApplicationContext context;

    @Bean
    public CircularDependencyA getCircularDependencyA() {
        return new CircularDependencyA();
    }

    @Bean
    public CircularDependencyB getCircularDependencyB() {
        return new CircularDependencyB();
    }

    @Test
    public void givenCircularDependency_whenSetterInjection_thenItWorks() {
        CircularDependencyA circA = context.getBean(CircularDependencyA.class);

        Assert.assertEquals("Hi!", circA.getCircB().getMessage());
    }
}

The following explains the annotations seen above:

@Bean: To tell Spring framework that these methods must be used to retrieve an implementation of the beans to inject.

@Test: The test will get CircularDependencyA bean from the context and assert that its CircularDependencyB has been injected properly, checking the value of its message property.

4.4. Use @PostConstruct

Another way to break the cycle is injecting a dependency using @Autowired on one of the beans, and then use a method annotated with @PostConstruct to set the other dependency.

Our beans could have the following code:

@Component
public class CircularDependencyA {

    @Autowired
    private CircularDependencyB circB;

    @PostConstruct
    public void init() {
        circB.setCircA(this);
    }

    public CircularDependencyB getCircB() {
        return circB;
    }
}
@Component
public class CircularDependencyB {

    private CircularDependencyA circA;
	
    private String message = "Hi!";

    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }
	
    public String getMessage() {
        return message;
    }
}

And we can run the same test we previously had, so we check that the circular dependency exception is still not being thrown and that the dependencies are properly injected.

4.5. Implement ApplicationContextAware and InitializingBean

If one of the beans implements ApplicationContextAware, the bean has access to Spring context and can extract the other bean from there. Implementing InitializingBean we indicate that this bean has to do some actions after all its properties have been set; in this case, we want to manually set our dependency.

The code of our beans would be:

@Component
public class CircularDependencyA implements ApplicationContextAware, InitializingBean {

    private CircularDependencyB circB;

    private ApplicationContext context;

    public CircularDependencyB getCircB() {
        return circB;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        circB = context.getBean(CircularDependencyB.class);
    }

    @Override
    public void setApplicationContext(final ApplicationContext ctx) throws BeansException {
        context = ctx;
    }
}
@Component
public class CircularDependencyB {

    private CircularDependencyA circA;

    private String message = "Hi!";

    @Autowired
    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }

    public String getMessage() {
        return message;
    }
}

Again, we can run the previous test and see that the exception is not thrown and that the test is working as expected.

5. In Conclusion

There are many ways to deal with circular dependencies in Spring. The first thing to consider is to redesign your beans so there is no need for circular dependencies: they are usually a symptom of a design that can be improved.

But if you absolutely need to have circular dependencies in your project, you can follow some of the workarounds suggested here.

The preferred method is using setter injections. But there are other alternatives, generally based on stopping Spring from managing the initialization and injection of the beans, and doing that yourself using one strategy or another.

You can find the beans shown above here, and the unit test here.

1 day left to get the early-bird price (20% Off) of my upcoming "Learn Spring Security" Course:

>> CHECK OUT THE COURSE

Java Web Weekly, Issue 134

$
0
0

I just released the Starter Class of "Learn Spring Security":

>> CHECK OUT THE COURSE

At the very beginning of last year, I decided to track my reading habits and share the best stuff here, on Baeldung. Haven’t missed a review since.

Here we go…

1. Spring and Java

>> Zero Turnaround releases RebelLabs Developer Productivity Report [infoq.com]

Let’s start with the yearly report from RebelLabs, providing some very interesting insights into the trends of our ecosystem.

>> How we fixed all database connection leaks [in.relation.to]

Very cool, to the point walk-through how the connection leaks in the large Hibernate test suite were handled.

>> JUnit 5 – An Early Test Drive – Part 1 [infoq.com]

An early look at the upcoming JUnit 5.

>> Notes on Reactive Programming Part III: A Simple HTTP Server Application [spring.io]

Reactive programing is coming to Spring with version 5 – we know that by now.

The question is – what are the scenarios where it’s going to make a significant difference and how can we use it before Spring 5 comes out.

And this new installment does a good job answering both of these questions.

>> Custom Audit Log With Spring And Hibernate [bozho.net]

There are projects where you can use some of the nicer ways of doing audit. And then there are some codebases where that’s not possible without major and painful refactoring. Luckily, there’s a clean, manual way of doing audit as well.

Also worth reading:

Webinars and presentations:

Time to upgrade:

2. Technical

>> The Hardest Part About Microservices: Your Data [christianposta.com]

Data is of course the most complex part of doing Microservices well, and in my experience, the number one reason teams fail during these kinds of implementations.

It turns out that, for example – getting transactional boundaries right across multiple systems is a hard problem to solve, especially without a very good understanding of the semantics to achieve in the system and a clear set of self-imposed limitations at the start.

>> An approach to test your user interface more efficiently [ontestautomation.com]

A quick, interesting read using a pattern I knew very little about – Model-View-ViewModel.

Also worth reading:

3. Musings

>> How to De-Brilliant Your Code [daedtech.com]

I enjoy reading through these listener questions, as they’re a nice change of pace.

And, just as a quick side-note, writing a feature without using the if keyword anywhere is certainly a nice way to spend the weekend 🙂

>> How to Add Static Analysis to Your Process [daedtech.com]

An intro to the thinking, expectations and how-to of dipping your toe into the deep waters of static analysis.

>> Managing rapid growth [dandreamsofcoding.com]

During the last couple of years, the company I’m working for has grown from 2 to more than 600-700 (last time I checked).

It’s definitely quite a ride to go through that kind of growth, and this writeup makes some good points about how to do that well.

>> Sources of Inspiration [daedtech.com]

A quick read, a solid reading list and some inspiration.

Also worth reading:

4. Comics

And my favorite Dilberts of the week:

>> Why did you reject my friend request on Facebook? [dilbert.com]

>> I trust them like I trust you [dilbert.com]

>> Stop saying what you’re thinking [dilbert.com]

5. Pick of the Week

This week, I finally finished and launched Learn Spring Security.

It’s been one hell of a week – which is why I’m writing this in the nick of time instead of several days before hitting publish, like I usually do.

Here it is:

>> The Master Class of Learn Spring Security [baeldung.com]

 

Get the early-bird price (20% Off) of my upcoming "Learn Spring Security" Course:

>> CHECK OUT THE COURSE

Quick Guide to @RestClientTest in Spring Boot

$
0
0

The Master Class of "Learn Spring Security" is out:

>> CHECK OUT THE COURSE

1. Introduction

This article is a quick introduction to a new feature of the upcoming Spring Boot 1.4.0 release — the @RestClientTest annotation.

The new annotation helps simplify and speed up the testing of REST clients in your Spring applications.

And of course it’s already available as a part of the first release candidate Spring Boot 1.4.0.

2. REST Client Support in Spring Boot Pre-1.4

Spring Boot is a handy framework that provides many auto-configured Spring beans with typical settings that allow you to concentrate less on configuration of a Spring application and more on your code and business logic.

But in version 1.3 we don’t get a lot of help when we want to create or test REST services clients. Its support for REST clients is not very deep.

To create a client for a REST API – a RestTemplate instance is typically used. Usually it has to be configured before usage and its configuration may vary, so Spring Boot does not provide any universally configured RestTemplate bean.

Same goes for testing REST clients. Before Spring Boot 1.4.0, the procedure of testing a Spring REST client was not very different than in any other Spring-based application. You would create a MockRestServiceServer instance, bind it to RestTemplate instance under test and provide it with mock responses to requests, like this:

RestTemplate restTemplate = new RestTemplate();

MockRestServiceServer mockServer =
  MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(requestTo("/greeting"))
  .andRespond(withSuccess());

// Test code that uses the above RestTemplate ...

mockServer.verify();

You would also have to initialize the Spring container and make sure that only the needed components are loaded into the context, to speed up the context load time (and consequently, the test execution time).

3. New REST Client Features in Spring Boot 1.4

In Spring Boot 1.4, the team has made a solid effort to simplify and speed up the creation and testing of REST clients.

So, let’s check out the new features.

3.1. Adding Spring Boot 1.4.0 to Your Project

First, you’ll need to make sure your project is using Spring Boot 1.4.x:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.0.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

And if you read this article prior to 1.4.0 release, you should also make sure to include Spring snapshot and milestone repositories, as described in the article “Spring Maven Repositories”, and use Spring Boot version 1.4.0.RC1. Newest release versions can be found here.

3.2. RestTemplateBuilder

Spring Boot 1.4 brings both the auto-configured RestTemplateBuilder to simplify creating RestTemplates, and the matching @RestClientTest annotation to test the clients built with RestTemplateBuilder. Here’s how you can create a simple REST client with RestTemplateBuilder auto-injected for you:

@Service
public class DetailsServiceClient {

    private final RestTemplate restTemplate;

    public DetailsServiceClient(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder.build();
    }

    public Details getUserDetails(String name) {
        return restTemplate.getForObject("/{name}/details",
          Details.class, name);
    }
}

Notice that we did not explicitly wire the RestTemplateBuilder instance to a constructor. This is possible thanks to a new Spring 4.3 feature called implicit constructor injection, which is discussed in this article. 

RestTemplateBuilder provides convenience methods for registering message converters, error handlers, URI template handlers, basic authorization and also use any additional customizers that you need.

3.3. @RestClientTest

For testing such a REST client built with RestTemplateBuilder, you may use a SpringRunner-executed test class annotated with @RestClientTest. This annotation disables full auto-configuration and only applies configuration relevant to REST client tests, i.e. Jackson or GSON auto-configuration and @JsonComponent beans, but not regular @Component beans.

@RestClientTest ensures that Jackson and GSON support is auto-configured, and also adds pre-configured RestTemplateBuilder and MockRestServiceServer instances to the context. The bean under test is specified with value or components attribute of the @RestClientTest annotation:

@RunWith(SpringRunner.class)
@RestClientTest(DetailsServiceClient.class)
public class DetailsServiceClientTest {

    @Autowired
    private DetailsServiceClient client;

    @Autowired
    private MockRestServiceServer server;

    @Autowired
    private ObjectMapper objectMapper;

    @Before
    public void setUp() throws Exception {
        String detailsString = 
          objectMapper.writeValueAsString(new Details("John Smith", "john"));
        
        this.server.expect(requestTo("/john/details"))
          .andRespond(withSuccess(detailsString, MediaType.APPLICATION_JSON));
    }

    @Test
    public void whenCallingGetUserDetails_thenClientMakesCorrectCall() 
      throws Exception {

        Details details = this.client.getUserDetails("john");

        assertThat(details.getLogin()).isEqualTo("john");
        assertThat(details.getName()).isEqualTo("John Smith");
    }
}

Firstly, we need to ensure that this test is run with SpringRunner by adding the @RunWith(SpringRunner.class) annotation.

So, what’s new?

First – the @RestClientTest annotation allows us to specify the exact service under test – in our case it is the DetailsServiceClient class. This service will be loaded into the test context, while everything else is filtered out.

This allows us to autowire the DetailsServiceClient instance inside our test and leave everything else outside, which speeds up the loading of the context.

Second – as the MockRestServiceServer instance is also configured for a @RestClientTest-annotated test (and bound to the DetailsServiceClient instance for us), we can simply inject it and use.

Finally – JSON support for @RestClientTest allows us to inject the Jackson’s ObjectMapper instance to prepare the MockRestServiceServer’s mock answer value.

All that is left to do is to execute the call to our service and verify the results.

4. Conclusion

In this article we’ve discussed the new @RestClientTest annotation that allows easy and quick testing of REST clients built with Spring and is expected in the upcoming Spring Boot 1.4.0 release.

The source code for the article is available on GitHub.

The Master Class of "Learn Spring Security" is out:

>> CHECK OUT THE COURSE

A Guide to REST-assured

$
0
0

I just announced the Master Class of my "REST With Spring" Course:

>> THE "REST WITH SPRING" CLASSES

1. Introduction

REST-assured was designed to simplify the testing and validation of REST APIs and is highly influenced by testing techniques used in dynamic languages such as Ruby and Groovy.

The library has solid support for HTTP, starting of course with the verbs and standard HTTP operations, but also going well beyond these basics.

In this guide, we are going to explore REST-assured and we’re going to use Hamcrest to do assertion. If you are not already familiar with Hamcrest, you should first brush up with the tutorial: Testing with Hamcrest.

Let’s dive in with a simple example.

2. Simple Example Test

Before we get started ensure that your tests have the following static imports:

io.restassured.RestAssured.*
io.restassured.matcher.RestAssuredMatchers.*
org.hamcrest.Matchers.*

We’ll need that to keep tests simple and have easy access to the main APIs.

Now, let’s get started with the simple example – a basic betting system exposing some data for games:

{
    "id": "390",
    "data": {
        "leagueId": 35,
        "homeTeam": "Norway",
        "visitingTeam": "England",
    },
    "odds": [{
        "price": "1.30",
        "name": "1"
    },
    {
        "price": "5.25",
        "name": "X"
    }]
}

Let’s say that this is the JSON response from hitting the locally deployed API – http://localhost:8080/events?id=390. :

Let’s now use REST-assured to verify some interesting features of the response JSON:

@Test
public void givenUrl_whenSuccessOnGetsResponseAndJsonHasRequiredKV_thenCorrect() {
   get("/events?id=390").then().statusCode(200).assertThat()
      .body("data.leagueId", equalTo(35)); 
}

So, what we did here is – we verified that a call to the endpoint /events?id=390 responds with a body containing a JSON String whose leagueId of the data object is 35.

Let’s have a look at a more interesting example. Let’s say you would like to verify that the odds array has records with prices 1.30 and 5.25:

@Test
public void givenUrl_whenJsonResponseHasArrayWithGivenValuesUnderKey_thenCorrect() {
   get("/events?id=390").then().assertThat()
      .body("odds.price", hasItems("1.30", "5.25"));
}

3. REST-assured Setup

If your favorite dependency tool is Maven, we add the following dependency in the pom.xml file:

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>3.0.0</version>
    <scope>test</scope>
</dependency>

To get the latest version, follow this link.

In addition, we may prefer to validate the JSON response based on a predefined JSON schema. In this case, we need to also include the json-schema-validator module in the pom.xml file:

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>3.0.0</version>
</dependency>

To ensure you have the latest version, follow this link.

We also need another library with the same name but a different author and functionality. It is not a module from REST-assured but rather, it is used under the hood by the json-schema-validator to perform validation.

Let’s add it like so:

<dependency>
    <groupId>com.github.fge</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>2.2.6</version>
</dependency>

It’s latest version can be found here.

The library, json-schema-validator, may also need the json-schema-core dependency:

<dependency>
    <groupId>com.github.fge</groupId>
    <artifactId>json-schema-core</artifactId>
    <version>1.2.5</version>
</dependency>

and the latest version is always found here.

REST-assured takes advantage of the power of Hamcrest matchers to perform it’s assertion, so we must include that dependency as well:

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-all</artifactId>
    <version>1.3</version>
</dependency>

The latest version will always be available at this link.

4. JSON Schema Validation

From time to time it may be desirable, without analyzing the response in detail, to know first-off whether the JSON body conforms to a certain JSON format.

Let’s have a look at an examples. Assume the JSON introduced in the above example has been saved in a file called event_0.json, and the file is present in the classpath, we can then use this JSON as a definition of our schema.

Then assuming that this is the general format followed by all data returned by our REST API, we can then check a JSON response for conformance like so:

@Test
public void givenUrl_whenJsonResponseConformsToSchema_thenCorrect() {
    get("/events?id=390").then().assertThat()
      .body(matchesJsonSchemaInClasspath("event_0.json"));
}

Notice that we’ll still statically import matchesJsonSchemaInClasspath from io.restassured.module.jsv.JsonSchemaValidator just as we do for all other methods.

5. JSON Schema Validation Settings

5.1. Validate a Response

The json-schema-validator module of REST-assured allows us the power to perform fine grained validation by defining our own custom configuration rules.

Say we want our validation to always use the JSON schema version 4:

@Test
public void givenUrl_whenValidatesResponseWithInstanceSettings_thenCorrect() {
    JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.newBuilder()
      .setValidationConfiguration(
        ValidationConfiguration.newBuilder()
          .setDefaultVersion(SchemaVersion.DRAFTV4).freeze())
            .freeze();
    get("/events?id=390").then().assertThat()
      .body(matchesJsonSchemaInClasspath("event_0.json")
        .using(jsonSchemaFactory));
}

We would do this by using the JsonSchemaFactory and specify the version 4 SchemaVersion and assert that it is using that schema when a request is made.

5.2. Check Validations

By default, the json-schema-validator runs checked validations on the JSON response String. This means that if the schema defines odds as an array as in the following JSON:

{
    "odds": [{
        "price": "1.30",
        "name": "1"
    },
    {
        "price": "5.25",
        "name": "X"
    }]
}

then the validator will always be expecting an array as the value for odds, hence a response where odds is a String will fail validation. So, if we would like to be less strict with our responses, we can add a custom rule during validation by first making the following static import:

io.restassured.module.jsv.JsonSchemaValidatorSettings.settings;

then execute the test with the validation check set to false:

@Test
public void givenUrl_whenValidatesResponseWithStaticSettings_thenCorrect() {
    get("/events?id=390").then().assertThat().body(matchesJsonSchemaInClasspath
      ("event_0.json").using(settings().with().checkedValidation(false)));
}

5.3. Global Validation Configuration

These customizations are very flexible, but with a large number of tests we would have to define a validation for each test, this is cumbersome and not very maintainable.

To avoid this, we have the freedom to define our configuration just once and let it apply to all tests.

We will configure the validation to be unchecked and to always use it against JSON schema version 3:

JsonSchemaFactory factory = JsonSchemaFactory.newBuilder()
  .setValidationConfiguration(
   ValidationConfiguration.newBuilder()
    .setDefaultVersion(SchemaVersion.DRAFTV3)
      .freeze()).freeze();
JsonSchemaValidator.settings = settings()
  .with().jsonSchemaFactory(factory)
      .and().with().checkedValidation(false);

then to remove this configuration call the reset method:

JsonSchemaValidator.reset();

5. Anonymous JSON Root Validation

Consider an array that comprises of primitives rather than objects:

[1, 2, 3]

This is called an anonymous JSON root, meaning that it has no key-value pair nevertheless it is still valid JSON data.

We can run validation in such a scenario by using the $ symbol or an empty String ( “” ) as path. Assume we expose the above service through http://localhost:8080/json then we can validate it like this with REST-assured:

when().get("/json").then().body("$", hasItems(1, 2, 3));

or like this:

when().get("/json").then().body("", hasItems(1, 2, 3));

6. Floats and Doubles

When we start using REST-assured to test our REST services, we need to understand that floating point numbers in JSON responses are mapped to primitive type float.

The use of float type is not interchangeable with double as is the case for many scenarios in java.

Case in point is this response:

{
    "odd": {
        "price": "1.30",
        "ck": 12.2,
        "name": "1"
    }
}

assume we are running the following test on the value of ck:

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2));

This test will fail even if the value we are testing is equal to the value in the response. This is because we are comparing to a double rather than to a float.

To make it work, we have to explicitly specify the operand to the equalTo matcher method as a float, like so:

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2f));

7. XML Response Verification

Not only can you validate a JSON response you can validate XML as well.

Let’s assume we make a request to http://localhost:8080/employees and we get the following response:

<employees>
    <employee category="skilled">
        <first-name>Jane</first-name>
        <last-name>Daisy</last-name>
        <sex>f</sex>
    </employee>
</employees>

We can verify that the first-name is Jane like so:

@Test
public void givenUrl_whenXmlResponseValueTestsEqual_thenCorrect() {
    post("/employees").then().assertThat()
      .body("employees.employee.first-name", equalTo("Jane"));
}

We can also verify that all values match our expected values by chaining body matchers together like so:

@Test
public void givenUrl_whenMultipleXmlValuesTestEqual_thenCorrect() {
    post("/employees").then().assertThat()
      .body("employees.employee.first-name", equalTo("Jane"))
        .body("employees.employee.last-name", equalTo("Daisy"))
          .body("employees.employee.sex", equalTo("f"));
}

Or using the short hand version with variable arguments:

@Test
public void givenUrl_whenMultipleXmlValuesTestEqualInShortHand_thenCorrect() {
    post("/employees")
      .then().assertThat().body("employees.employee.first-name", 
        equalTo("Jane"),"employees.employee.last-name", 
          equalTo("Daisy"), "employees.employee.sex", 
            equalTo("f"));
}

8. XPath for XML

We can verify our responses using XPath. Consider the example below that executes a matcher on the first-name:

@Test
public void givenUrl_whenValidatesXmlUsingXpath_thenCorrect() {
    post("/employees").then().assertThat().
      body(hasXPath("/employees/employee/first-name", containsString("Ja")));
}

XPath also accepts an alternate way of running the equalTo matcher:

@Test
public void givenUrl_whenValidatesXmlUsingXpath2_thenCorrect() {
    post("/employees").then().assertThat()
      .body(hasXPath("/employees/employee/first-name[text()='Jane']"));
}

9. Using Groovy

Since Rest-assured uses Groovy under the hood, we actually have the opportunity to use raw Groovy syntax to create more powerful test cases. This is where the framework really comes to life.

9.1. Groovy’s Collection API

If Groovy is new to you, read on, otherwise you can skip to the section Validate JSON with Groovy.

We will take a quick look at some basic Groovy concepts with a simple examples to equip us with just what we need.

9.2. The findAll method

In this example, we will just pay attention to methods, closures and the it implicit variable. Let us first create a Groovy collection of words:

def words = ['ant', 'buffalo', 'cat', 'dinosaur']

Let’s now create another collection out of the above with words with lengths that exceed four letters:

def wordsWithSizeGreaterThanFour = words.findAll { it.length() > 4 }

Here, findAll is a method applied to the collection with a closure applied to the method. The method defines what logic to apply to the collection and the closure gives the method a predicate to customize the logic.

We are telling Groovy to loop through the collection and find all words whose length is greater than four and return the result into a new collection.

9.3. The it variable

The implicit variable it holds the current word in the loop. The new collection wordsWithSizeGreaterThanFour will contain the words buffalo and dinosaur.

['buffalo', 'dinosaur']

Apart from findAll, there are other Groovy methods.

9.4. The collect iterator

Finally, there is collect, it calls the closure on each item in the collection and returns a new collection with the results of each. Let’s create a new collection out of the sizes of each item in the words collection:

def sizes = words.collect{it.length()}

The result:

[3,7,3,8]

We use sum, as the name suggests to add up all elements in the collection. We can sum up the items in the sizes collection like so:

def charCount = sizes.sum()

and the result will be 21, the character count of all the items in the words collection.

9.5. The max/min operators

The max/min operators are intuitively named to find the maximum or minimum number in a collection :

def maximum = sizes.max()

The result should be obvious, 8.

9.6. The find iterator

We use find to search for only one collection value matching the closure predicate.

def greaterThanSeven=sizes.find{it>7}

The result, 8, the first occurrence of the collection item that meets the predicate.

10. Validate JSON with Groovy

If we have a service at http://localhost:8080/odds, that returns a list of odds of our favorite football matches, like this:

{
    "odds": [{
        "price": 1.30,
        "status": 0,
        "ck": 12.2,
        "name": "1"
    },
    {
        "price": 5.25,
        "status": 1,
        "ck": 13.1,
        "name": "X"
    },
    {
        "price": 2.70,
        "status": 0,
        "ck": 12.2,
        "name": "0"
    },
    {
        "price": 1.20,
        "status": 2,
        "ck": 13.1,
        "name": "2"
    }]
}

and if we want to verify that the odds with a status greater than 1 have prices 1.20 and 5.25, then we do this:

@Test
public void givenUrl_whenVerifiesOddPricesAccuratelyByStatus_thenCorrect() {
    get("/odds").then().body("odds.findAll { it.status > 0 }.price",
      hasItems(5.25f, 1.20f));
}

What is happening here is this; we use Groovy syntax to load the JSON array under the key odds. Since it has more than one item, we obtain a Groovy collection. We then invoke the findAll method on this collection.

The closure predicate tells Groovy to create another collection with JSON objects where status is greater than zero.

We end our path with price which tells groovy to create another list of only prices of the odds in our previous list of JSON objects. We then apply the hasItems Hamcrest matcher to this list.

11. Validate XML with Groovy

Let’s assume we have a service at http://localhost:8080/teachers, that returns a list of teachers by their id, department and subjects taught as below:

<teachers>
    <teacher department="science" id=309>
        <subject>math</subject>
        <subject>physics</subject>
    </teacher>
    <teacher department="arts" id=310>
        <subject>political education</subject>
        <subject>english</subject>
    </teacher>
</teachers>

Now we can verify that the science teacher returned in the response teaches both math and physics:

@Test
public void givenUrl_whenVerifiesScienceTeacherFromXml_thenCorrect() {
    get("/teachers").then().body(
      "teachers.teacher.find { it.@department == 'science' }.subject",
        hasItems("math", "physics"));
}

We have used the XML path teachers.teacher to get a list of teachers by the XML attribute, department. We then call the find method on this list.

Our closure predicate to find ensures we end up with only teachers from the science department. Our XML path terminates at the subject tag.

Since there is more than one subject, we will get a list which we validate with the hasItems Hamcrest matcher.

11. Conclusion

In this tutorial, we have explored the REST-assured framework and looked at its most important features which we can use to test our RESTful services and validate their responses.

The full implementation of all these examples and code snippets can be found in the REST-assured github project.

The Master Class of my "REST With Spring" Course is finally out:

>> CHECK OUT THE CLASSES

A Guide to FastJson

$
0
0

I usually post about Jackson and JSON stuff on Twitter - you can follow me there:

1. Overview

FastJson is a lightweight Java library used to effectively convert JSON strings to Java objects and vice versa.

In this article we’re going to dive into several concrete and practical applications of the FastJson library.

2. Maven Configuration

In order to start working with FastJson, we first need to add that to our pom.xml:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.13</version>
</dependency>

And as a quick note – here’s the most updated version of the library on Maven Central.

3. Convert Java Objects to JSON Format

Let’s define the following Person Java bean:

public class Person {
    
    @JSONField(name = "AGE")
    private int age;

    @JSONField(name = "FULL NAME")
    private String fullName;

    @JSONField(name = "DATE OF BIRTH")
    private Date dateOfBirth;

    public Person(int age, String fullName, Date dateOfBirth) {
        super();
        this.age = age;
        this.fullName= fullName;
        this.dateOfBirth = dateOfBirth;
    }

    // standard getters & setters
}

We can use JSON.toJSONString() to convert a Java object to a JSON String:

private List<Person> listOfPersons = new ArrayList<Person>();

@Before
public void setUp() {
    listOfPersons.add(new Person(15, "John Doe", new Date()));
    listOfPersons.add(new Person(20, "Janette Doe", new Date()));
}

@Test
public void whenJavaList_thanConvertToJsonCorrect() {
    String jsonOutput= JSON.toJSONString(listOfPersons);
}

And here’s the result:

[  
    {  
        "AGE":15,
        "DATE OF BIRTH":1468962431394,
        "FULL NAME":"John Doe"
    },
    {  
        "AGE":20,
        "DATE OF BIRTH":1468962431394,
        "FULL NAME":"Janette Doe"
    }
]

We can also go further and start customizing the output and control things like ordering, date formatting, or serialization flags.

For example – let’s update the bean and add a couple more fields:

@JSONField(name="AGE", serialize=false)
private int age;

@JSONField(name="LAST NAME", ordinal = 2)
private String lastName;

@JSONField(name="FIRST NAME", ordinal = 1)
private String firstName;

@JSONField(name="DATE OF BIRTH", format="dd/MM/yyyy", ordinal = 3)
private Date dateOfBirth;

Here’s a list of the most basic parameters that we can use alongside the @JSONField annotation, in order to customize the conversion process:

  • The parameter format is used to properly format the date attribute
  • By default, the FastJson library serialize the Java bean entirely, but we can make use of the parameter serialize to ignore serialization for specific fields
  • The parameter ordinal is used to specify the fields order

And here’s the new output:

[
    {
        "FIRST NAME":"Doe",
        "LAST NAME":"Jhon",
        "DATE OF BIRTH":"19/07/2016"
    },
    {
        "FIRST NAME":"Doe",
        "LAST NAME":"Janette",
        "DATE OF BIRTH":"19/07/2016"
    }
]

FastJson also supports a very interesting BeanToArray serialization feature:

String jsonOutput= JSON.toJSONString(listOfPersons, SerializerFeature.BeanToArray);

Here’s what the output will look like in this case:

[
    [
        15,
        1469003271063,
        "John Doe"
    ],
    [
        20,
        1469003271063,
        "Janette Doe"
    ]
]

4. Create JSON Objects

Like other JSON libraries, creating a JSON object from scratch is pretty straightforward, it’s only a matter of combining JSONObject and JSONArray objects:

@Test
public void whenGenerateJson_thanGenerationCorrect() throws ParseException {
    JSONArray jsonArray = new JSONArray();
    for (int i = 0; i < 2; i++) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("AGE", 10);
        jsonObject.put("FULL NAME", "Doe " + i);
        jsonObject.put("DATE OF BIRTH", "2016/12/12 12:12:12");
        jsonArray.add(jsonObject);
    }
    String jsonOutput = jsonArray.toJSONString();
}

And here’s what the output will look like here:

[
   {
      "AGE":"10",
      "DATE OF BIRTH":"2016/12/12 12:12:12",
      "FULL NAME":"Doe 0"
   },
   {
      "AGE":"10",
      "DATE OF BIRTH":"2016/12/12 12:12:12",
      "FULL NAME":"Doe 1"
   }
]

5. Parse JSON Strings into Java Objects

Now that we know how to create a JSON object from scratch, and how to convert Java objects to their JSON representations, let’s put the focus on how to parse a JSON representation:

@Test
public void whenJson_thanConvertToObjectCorrect() {
    Person person = new Person(20, "John", "Doe", new Date());
    String jsonObject = JSON.toJSONString(person);
    Person newPerson = JSON.parseObject(jsonObject, Person.class);
    
    assertEquals(newPerson.getAge(), 0); // if we set serialize to false
    assertEquals(newPerson.getFullName(), listOfPersons.get(0).getFullName());
}

We can use JSON.parseObject() to get a Java object from a JSON String.

Note that you have to define a no-args or default constructor if you have already declared your own parametrized one, otherwise a com.alibaba.fastjson.JSONException will be thrown.

Here’s the output of this simple test:

Person [age=20, fullName=John Doe, dateOfBirth=Wed Jul 20 08:51:12 WEST 2016]

By using the option deserialize inside the @JSONField annotation, we can ignore deserialization for a specific field, in this case, the default value will apply automatically to the ignored field:

@JSONField(name = "DATE OF BIRTH", deserialize=false)
private Date dateOfBirth;

And here’s the newly created object:

Person [age=20, fullName=John Doe, dateOfBirth=null]

6. Configure JSON Conversion Using ContextValueFilter

In some scenarios, we may need to have more control over the conversion process from Java objects to JSON format.

In this case we can make use of the ContextValueFilter object to apply additional filtering and custom processing to the conversion flow:

@Test
public void givenContextFilter_whenJavaObject_thanJsonCorrect() {
    ContextValueFilter valueFilter = new ContextValueFilter () {
        public Object process(
          BeanContext context, Object object, String name, Object value) {
            if (name.equals("DATE OF BIRTH")) {
                return "NOT TO DISCLOSE";
            }
            if (value.equals("John")) {
                return ((String) value).toUpperCase();
            } else {
                return null;
            }
        }
    };
    String jsonOutput = JSON.toJSONString(listOfPersons, valueFilter);
}

In this example, we hid the DATE OF BIRTH field, by forcing a constant value, we also ignored all fields that are not John or Doe:

[
    {
        "FULL NAME":"JOHN DOE",
        "DATE OF BIRTH":"NOT TO DISCLOSE"
    }
]

As you can see, this is a pretty basic example, but you can of course use the same concepts for more complex scenarios as well – combining these powerful and lightweight set of tools offered by FastJson in a real world project.

7. Using NameFilter and SerializeConfig

FastJson offers a set of tools to customize you JSON operations when dealing with arbitrary object – objects we don’t have the source code of.

Let’s imagine we have a compiled version of the Person Java bean, initially declared in this article, and we need to make some enhancement on fields naming and basic formatting:

@Test
public void givenSerializeConfig_whenJavaObject_thanJsonCorrect() {
    NameFilter formatName = new NameFilter() {
        public String process(Object object, String name, Object value) {
            return name.toLowerCase().replace(" ", "_");
        }
    };
    
    SerializeConfig.getGlobalInstance().addFilter(Person.class,  formatName);
    String jsonOutput = 
      JSON.toJSONStringWithDateFormat(listOfPersons, "yyyy-MM-dd");
}

We’ve declared the formatName filter using the NameFilter anonymous class to process fields names. The newly created filter is associated to the Person class, and then added to a global instance – which is basically a static attribute in the SerializeConfig class.

Now we can comfortably convert our object to JSON format as shown earlier in this article.

Note that we’ve used toJSONStringWithDateFormat() instead of toJSONString() to quickly apply the same formatting rule on date fields.

And here’s the output:

[  
    {  
        "full_name":"John Doe",
        "date_of_birth":"2016-07-21"
    },
    {  
        "full_name":"Janette Doe",
        "date_of_birth":"2016-07-21"
    }
]

As you can see – the fields names got changed, and the date value did got properly formatted.

Combining SerializeFilter with ContextValueFilter can give full control over the conversion process for arbitrary and complex Java objects.

8. Conclusion

In this article we showed how to use FastJson to convert Java beans to JSON strings and how to go the other way around. We also showed how to use some of the core features of FastJson in order to customize the JSON output.

As you can see, the library offers a relatively simple to use but still very powerful API. JSON.toJSONString and JSON.parseObject are all you need to use in order to meet most of your needs – if not all.

You can checkout the examples provided in this article in the linked GitHub project.

I usually post about Jackson and JSON stuff on Twitter - you should follow me there:


Introduction To XMLUnit 2.x

$
0
0

The Master Class of "Learn Spring Security" is live:

>> CHECK OUT THE COURSE

1. Overview

XMLUnit 2.x is a powerful library that helps us test and verify XML content, and comes in particularly handy when we know exactly what that XML should contain.

And so we’ll mainly be using XMLUnit inside unit tests to verify that what we have is valid XML, that it contains certain information or conforms to a certain style document.

Additionally, with XMLUnit, we have control over what kind of difference is important to us and which part of the style reference to compare with which part of your comparison XML.

Since we are focusing on XMLUnit 2.x and not XMLUnit 1.x, whenever we use the word XMLUnit, we are strictly referring to 2.x.

Finally, we’ll also be using Hamcrest matchers for assertion, so it’s a good idea to to brush up on Hamcrest in case you are not familiar with it.

2. XMLUnit Maven Setup

To use the library in our maven projects, we need to have the following dependencies in pom.xml:

<dependency>
    <groupId>org.xmlunit</groupId>
    <artifactId>xmlunit-core</artifactId>
    <version>2.2.1</version>
</dependency>

The latest version of xmlunit-core can be found by following this link. And:

<dependency>
    <groupId>org.xmlunit</groupId>
    <artifactId>xmlunit-matchers</artifactId>
    <version>2.2.1</version>
</dependency>

The latest version of xmlunit-matchers is available at this link.

3. Comparing XML

3.1. Simple Difference Examples

Let’s assume we have two pieces of XML. They are deemed to be identical when the content and sequence of the nodes in the documents are exactly the same, so the following test will pass:

@Test
public void given2XMLS_whenIdentical_thenCorrect() {
    String controlXml = "<struct><int>3</int><boolean>false</boolean></struct>";
    String testXml = "<struct><int>3</int><boolean>false</boolean></struct>";
    assertThat(testXml, CompareMatcher.isIdenticalTo(controlXml));
}

This next test fails as the two pieces of XML are similar but not identical as their nodes occur in a different sequence:

@Test
public void given2XMLSWithSimilarNodesButDifferentSequence_whenNotIdentical_thenCorrect() {
    String controlXml = "<struct><int>3</int><boolean>false</boolean></struct>";
    String testXml = "<struct><boolean>false</boolean><int>3</int></struct>";
    assertThat(testXml, assertThat(testXml, not(isIdenticalTo(controlXml)));
}

3.2. Detailed Difference Example

Differences between two XML documents above are detected by the Difference Engine.

By default and for efficiency reasons, it stops the comparison process as soon as the first difference is found.

To get all the differences between two pieces of XML we use an instance of the Diff class like so:

@Test
public void given2XMLS_whenGeneratesDifferences_thenCorrect(){
    String controlXml = "<struct><int>3</int><boolean>false</boolean></struct>";
    String testXml = "<struct><boolean>false</boolean><int>3</int></struct>";
    Diff myDiff = DiffBuilder.compare(controlXml).withTest(testXml).build();
    
    Iterator<Difference> iter = myDiff.getDifferences().iterator();
    int size = 0;
    while (iter.hasNext()) {
        iter.next().toString();
        size++;
    }
    assertThat(size, greaterThan(1));
}

If we print the values returned in the while loop, the result is as below:

Expected element tag name 'int' but was 'boolean' - 
  comparing <int...> at /struct[1]/int[1] to <boolean...> 
    at /struct[1]/boolean[1] (DIFFERENT)
Expected text value '3' but was 'false' - 
  comparing <int ...>3</int> at /struct[1]/int[1]/text()[1] to 
    <boolean ...>false</boolean> at /struct[1]/boolean[1]/text()[1] (DIFFERENT)
Expected element tag name 'boolean' but was 'int' - 
  comparing <boolean...> at /struct[1]/boolean[1] 
    to <int...> at /struct[1]/int[1] (DIFFERENT)
Expected text value 'false' but was '3' - 
  comparing <boolean ...>false</boolean> at /struct[1]/boolean[1]/text()[1] 
    to <int ...>3</int> at /struct[1]/int[1]/text()[1] (DIFFERENT)

Each instance describes both the type of difference found between a control node and test node and the detail of those nodes (including the XPath location of each node).

If we want to force the Difference Engine to stop after the first difference is found and not proceed to enumerate further differences – we need to supply a ComparisonController:

@Test
public void given2XMLS_whenGeneratesOneDifference_thenCorrect(){
    String myControlXML = "<struct><int>3</int><boolean>false</boolean></struct>";
    String myTestXML = "<struct><boolean>false</boolean><int>3</int></struct>";
    
    Diff myDiff = DiffBuilder
      .compare(myControlXML)
      .withTest(myTestXML)
      .withComparisonController(ComparisonControllers.StopWhenDifferent)
       .build();
    
    Iterator<Difference> iter = myDiff.getDifferences().iterator();
    int size = 0;
    while (iter.hasNext()) {
        iter.next().toString();
        size++;
    }
    assertThat(size, equalTo(1));
}

The difference message is simpler:

Expected element tag name 'int' but was 'boolean' - 
  comparing <int...> at /struct[1]/int[1] 
    to <boolean...> at /struct[1]/boolean[1] (DIFFERENT)

4. Input Sources

With XMLUnit, we can pick XML data from a variety of sources that may be convenient for our application’s needs. In this case, we use the Input class with its array of static methods.

To pick input from an XML file located in the project root, we do the following:

@Test
public void givenFileSource_whenAbleToInput_thenCorrect() {
    ClassLoader classLoader = getClass().getClassLoader();
    String testPath = classLoader.getResource("test.xml").getPath();
    String controlPath = classLoader.getResource("control.xml").getPath();
    
    assertThat(
      Input.fromFile(testPath), isSimilarTo(Input.fromFile(controlPath)));
}

To pick an input source from an XML string, like so:

@Test
public void givenStringSource_whenAbleToInput_thenCorrect() {
    String controlXml = "<struct><int>3</int><boolean>false</boolean></struct>";
    String testXml = "<struct><int>3</int><boolean>false</boolean></struct>";
    
    assertThat(
      Input.fromString(testXml),isSimilarTo(Input.fromString(controlXml)));
}

Let’s now use a stream as the input:

@Test
public void givenStreamAsSource_whenAbleToInput_thenCorrect() {
    assertThat(Input.fromStream(XMLUnitTests.class
      .getResourceAsStream("/test.xml")),
        isSimilarTo(
          Input.fromStream(XMLUnitTests.class
            .getResourceAsStream("/control.xml"))));
}

We could also use Input.from(Object) where we pass in any valid source to be resolved by XMLUnit.

For example, we can pass a file in:

@Test
public void givenFileSourceAsObject_whenAbleToInput_thenCorrect() {
    ClassLoader classLoader = getClass().getClassLoader();
    
    assertThat(
      Input.from(new File(classLoader.getResource("test.xml").getFile())), 
      isSimilarTo(Input.from(new File(classLoader.getResource("control.xml").getFile()))));
}

Or a String:

@Test
public void givenStringSourceAsObject_whenAbleToInput_thenCorrect() {
    assertThat(
      Input.from("<struct><int>3</int><boolean>false</boolean></struct>"),
      isSimilarTo(Input.from("<struct><int>3</int><boolean>false</boolean></struct>")));
}

Or a Stream:

@Test
public void givenStreamAsObject_whenAbleToInput_thenCorrect() {
    assertThat(
      Input.from(XMLUnitTest.class.getResourceAsStream("/test.xml")), 
      isSimilarTo(Input.from(XMLUnitTest.class.getResourceAsStream("/control.xml"))));
}

and they will all be resolved.

5. Comparing Specific Nodes

In section 2 above, we only looked at identical XML because similar XML needs a little bit of customization using features from xmlunit-core library:

@Test
public void given2XMLS_whenSimilar_thenCorrect() {
    String controlXml = "<struct><int>3</int><boolean>false</boolean></struct>";
    String testXml = "<struct><boolean>false</boolean><int>3</int></struct>";
    
    assertThat(testXml, isSimilarTo(controlXml));
}

The above test should pass, since the XMLs have similar nodes, however it fails. This is because XMLUnit compares control and test nodes at the same depth relative to the root node.

So a isSimilarTo condition is a little bit more interesting to test than an isIdenticalTo condition. The node <int>3</int> in controlXml will be compared with <boolean>false</boolean> in testXml, automatically giving failure message:

java.lang.AssertionError: 
Expected: Expected element tag name 'int' but was 'boolean' - 
  comparing <int...> at /struct[1]/int[1] to <boolean...> at /struct[1]/boolean[1]:
<int>3</int>
   but: result was: 
<boolean>false</boolean>

This is where the DefaultNodeMatcher and ElementSelector classes of XMLUnit come in handy

The DefaultNodeMatcher class is consulted by XMLUnit at comparison stage as it loops over nodes of controlXml, to determine which XML node from testXml to compare with the current XML node it encounters in controlXml.

Before that, DefaultNodeMatcher will have already consulted ElementSelector to decide how to match nodes.

Our test has failed because in the default state, XMLUnit will use a depth-first approach to traverse the XMLs and based on document order to match nodes, hence <int> is matched with <boolean>.

Let’s tweak our test so that it passes:

@Test
public void given2XMLS_whenSimilar_thenCorrect() {
    String controlXml = "<struct><int>3</int><boolean>false</boolean></struct>";
    String testXml = "<struct><boolean>false</boolean><int>3</int></struct>";
    
    assertThat(testXml, 
      isSimilarTo(controlXml).withNodeMatcher(
      new DefaultNodeMatcher(ElementSelectors.byName)));
}

In this case we are telling DefaultNodeMatcher that when XMLUnit asks for a node to compare, you should have sorted and matched the nodes by their element names already.

The initial failed example was similar to passing ElementSelectors.Default to DefaultNodeMatcher.

Alternatively, we could have used a Diff from xmlunit-core rather than using xmlunit-matchers:

@Test
public void given2XMLs_whenSimilarWithDiff_thenCorrect() throws Exception {
    String myControlXML = "<struct><int>3</int><boolean>false</boolean></struct>";
    String myTestXML = "<struct><boolean>false</boolean><int>3</int></struct>";
    Diff myDiffSimilar = DiffBuilder.compare(myControlXML).withTest(myTestXML)
      .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))
      .checkForSimilar().build();
    
    assertFalse("XML similar " + myDiffSimilar.toString(),
      myDiffSimilar.hasDifferences());
}

6. Custom DifferenceEvaluator

A DifferenceEvaluator makes determinations of the outcome of a comparison. Its role is restricted to determining the severity of a comparison’s outcome.

It’s the class that decides whether two XML pieces are identical, similar or different.

Consider the following XML pieces:

<a>
    <b attr="abc">
    </b>
</a>

and:

<a>
    <b attr="xyz">
    </b>
</a>

In the default state, they are technically evaluated as different because their attr attributes have different values. Let’s take a look at a test:

@Test
public void given2XMLsWithDifferences_whenTestsDifferentWithoutDifferenceEvaluator_thenCorrect(){
    final String control = "<a><b attr=\"abc\"></b></a>";
    final String test = "<a><b attr=\"xyz\"></b></a>";
    Diff myDiff = DiffBuilder.compare(control).withTest(test)
      .checkForSimilar().build();
    assertFalse(myDiff.toString(), myDiff.hasDifferences());
}

Failure message:

java.lang.AssertionError: Expected attribute value 'abc' but was 'xyz' - 
  comparing <b attr="abc"...> at /a[1]/b[1]/@attr 
  to <b attr="xyz"...> at /a[1]/b[1]/@attr

If we don’t really care about the attribute, we can change the behaviour of DifferenceEvaluator to ignore it. We do this by creating our own:

public class IgnoreAttributeDifferenceEvaluator implements DifferenceEvaluator {
    private String attributeName;
    public IgnoreAttributeDifferenceEvaluator(String attributeName) {
        this.attributeName = attributeName;
    }
    
    @Override
    public ComparisonResult evaluate(Comparison comparison, ComparisonResult outcome) {
        if (outcome == ComparisonResult.EQUAL)
            return outcome;
        final Node controlNode = comparison.getControlDetails().getTarget();
        if (controlNode instanceof Attr) {
            Attr attr = (Attr) controlNode;
            if (attr.getName().equals(attributeName)) {
                return ComparisonResult.SIMILAR;
            }
        }
        return outcome;
    }
}

We then rewrite our initial failed test and supply our own DifferenceEvaluator instance, like so:

@Test
public void given2XMLsWithDifferences_whenTestsSimilarWithDifferenceEvaluator_thenCorrect() {
    final String control = "<a><b attr=\"abc\"></b></a>";
    final String test = "<a><b attr=\"xyz\"></b></a>";
    Diff myDiff = DiffBuilder.compare(control).withTest(test)
      .withDifferenceEvaluator(new IgnoreAttributeDifferenceEvaluator("attr"))
      .checkForSimilar().build();
    
    assertFalse(myDiff.toString(), myDiff.hasDifferences());
}

This time it passes.

7. Validation

XMLUnit performs XML validation using the Validator class. You create an instance of it using the forLanguage factory method while passing in the schema to use in validation.

The schema is passed in as a URI leading to its location, XMLUnit abstracts the schema locations it supports in the Languages class as constants.

We typically create an instance of Validator class like so:

Validator v = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);

After this step, if we have our own XSD file to validate against our XML, we simply specify its source and then call Validator‘s validateInstance method with our XML file source.

Take for example our students.xsd:

<?xml version = "1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name='class'>
        <xs:complexType>
            <xs:sequence>
                <xs:element name='student' type='StudentObject'
                   minOccurs='0' maxOccurs='unbounded' />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="StudentObject">
        <xs:sequence>
            <xs:element name="name" type="xs:string" />
            <xs:element name="age" type="xs:positiveInteger" />
        </xs:sequence>
        <xs:attribute name='id' type='xs:positiveInteger' />
    </xs:complexType>
</xs:schema>

And students.xml:

<?xml version = "1.0"?>
<class>
    <student id="393">
        <name>Rajiv</name>
        <age>18</age>
    </student>
    <student id="493">
        <name>Candie</name>
        <age>19</age>
    </student>
</class>

Let’s then run a test:

@Test
public void givenXml_whenValidatesAgainstXsd_thenCorrect() {
    Validator v = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);
    v.setSchemaSource(Input.fromStream(
      XMLUnitTests.class.getResourceAsStream("/students.xsd")).build());
    ValidationResult r = v.validateInstance(Input.fromStream(
      XMLUnitTests.class.getResourceAsStream("/students.xml")).build());
    Iterator<ValidationProblem> probs = r.getProblems().iterator();
    while (probs.hasNext()) {
        probs.next().toString();
    }
    assertTrue(r.isValid());
}

The result of the validation is an instance of ValidationResult which contains a boolean flag indicating whether the document has been validated successfully.

The ValidationResult also contains an Iterable with ValidationProblems in case there is a failure. Let’s create a new XML with errors called students_with_error.xml. Instead of <student>, our starting tags are all </studet>:

<?xml version = "1.0"?>
<class>
    <studet id="393">
        <name>Rajiv</name>
        <age>18</age>
    </student>
    <studet id="493">
        <name>Candie</name>
        <age>19</age>
    </student>
</class>

Then run this test against it:

@Test
public void givenXmlWithErrors_whenReturnsValidationProblems_thenCorrect() {
    Validator v = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);
    v.setSchemaSource(Input.fromStream(
       XMLUnitTests.class.getResourceAsStream("/students.xsd")).build());
    ValidationResult r = v.validateInstance(Input.fromStream(
      XMLUnitTests.class.getResourceAsStream("/students_with_error.xml")).build());
    Iterator<ValidationProblem> probs = r.getProblems().iterator();
    int count = 0;
    while (probs.hasNext()) {
        count++;
        probs.next().toString();
    }
    assertTrue(count > 0);
}

If we were to print the errors in the while loop, they would look like:

ValidationProblem { line=3, column=19, type=ERROR,message='cvc-complex-type.2.4.a: 
  Invalid content was found starting with element 'studet'. 
    One of '{student}' is expected.' }
ValidationProblem { line=6, column=4, type=ERROR, message='The element type "studet" 
  must be terminated by the matching end-tag "</studet>".' }
ValidationProblem { line=6, column=4, type=ERROR, message='The element type "studet" 
  must be terminated by the matching end-tag "</studet>".' }

8. XPath

When an XPath expression is evaluated against a piece of XML a NodeList is created that contains the matching Nodes.

Consider this piece of XML saved in a file called teachers.xml:

<teachers>
    <teacher department="science" id='309'>
        <subject>math</subject>
        <subject>physics</subject>
    </teacher>
    <teacher department="arts" id='310'>
        <subject>political education</subject>
        <subject>english</subject>
    </teacher>
</teachers>

XMLUnit offers a number of XPath related assertion methods, as demonstrated below.

We can retrieve all the nodes called teacher and perform assertions on them individually:

@Test
public void givenXPath_whenAbleToRetrieveNodes_thenCorrect() {
    Iterable<Node> i = new JAXPXPathEngine()
      .selectNodes("//teacher", Input.fromFile(new File("teachers.xml")).build());
    assertNotNull(i);
    int count = 0;
    for (Iterator<Node> it = i.iterator(); it.hasNext();) {
        count++;
        Node node = it.next();
        assertEquals("teacher", node.getNodeName());
        
        NamedNodeMap map = node.getAttributes();
        assertEquals("department", map.item(0).getNodeName());
        assertEquals("id", map.item(1).getNodeName());
        assertEquals("teacher", node.getNodeName());
    }
    assertEquals(2, count);
}

Notice how we validate the number of child nodes, the name of each node and the attributes in each node. Many more options are available after retrieving the Node.

To verify that a path exists, we can do the following:

@Test
public void givenXmlSource_whenAbleToValidateExistingXPath_thenCorrect() {
    assertThat(Input.fromFile(new File("teachers.xml")), hasXPath("//teachers"));
    assertThat(Input.fromFile(new File("teachers.xml")), hasXPath("//teacher"));
    assertThat(Input.fromFile(new File("teachers.xml")), hasXPath("//subject"));
    assertThat(Input.fromFile(new File("teachers.xml")), hasXPath("//@department"));
}

To verify that a path does not exist, this is what we can do:

@Test
public void givenXmlSource_whenFailsToValidateInExistentXPath_thenCorrect() {
    assertThat(Input.fromFile(new File("teachers.xml")), not(hasXPath("//sujet")));
}

XPaths are especially useful where a document is made up largely of known, unchanging content with only a small amount of changing content created by the system.

9. Conclusion

In this tutorial, we have introduced most of the basic features of XMLUnit 2.x and how to use them to validate XML documents in our applications.

The full implementation of all these examples and code snippets can be found in the XMLUnit github project.

I just released the Master Class of "Learn Spring Security" Course:

>> CHECK OUT THE COURSE

Intro to Spring Security Expressions

$
0
0

1. Introduction

In this tutorial we’ll focus on Spring Security Expressions, and of course on practical examples with these expressions.

Before looking at more complex implementations (such as ACL), it’s important to have a solid grasp on security expressions – as they can be quite flexible and powerful if used correctly.

This article is an extension of Spring Security Expressions – hasRole Example.

2. Maven Dependencies

In order to use Spring Security, you need to include the following section in your pom.xml file:

<dependencies>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>4.1.1.RELEASE</version>
    </dependency>
</dependencies>

Latest version can be found here.

And a quick note – this dependency only covers Spring Security; don’t forget to add spring-core and spring-context for a full web application.

3. Configuration

First, let’s take a look at a Java configuration.

We’ll extend WebSecurityConfigurerAdapter – so that we have the option to hook into any of the extension points that base class offers:

@Configuration
@EnableAutoConfiguration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter {
    ...
}

We can of course do an XML configuration as well:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans ...>
    <global-method-security pre-post-annotations="enabled"/>
</beans:beans>

4. Web Security Expressions

Now, let’s start looking at the security expressions:

  • hasRole, hasAnyRole
  • hasAuthority, hasAnyAuthority
  • permitAll, denyAll
  • isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticated
  • principal, authentication
  • hasPermission

And let’s now go over each of these in detail.

4.1. hasRole, hasAnyRole

These expressions are responsible for defining the access control or authorization to specific URLs or methods in your application.

Let’s look at the example:

@Override
protected void configure(final HttpSecurity http) throws Exception {
    ...
    .antMatchers("/auth/admin/*").hasRole("ADMIN")
    .antMatchers("/auth/*").hasAnyRole("ADMIN","USER")
    ...
}

In this example we specify access to all links starting with /auth/ restricted to users that are logged in with role USER or role ADMIN. Moreover, to access links starting with /auth/admin/ we need to have ADMIN role in the system.

The same configuration might be achieved in XML file, by writing:

<http>
    <intercept-url pattern="/auth/admin/*" access="hasRole('ADMIN')"/>
    <intercept-url pattern="/auth/*" access="hasAnyRole('ADMIN','USER')"/>
</http>

4.2. hasAuthority, hasAnyAuthority

Roles and authorities are similar in Spring.

The main difference is that, roles have special semantics – starting with Spring Security 4, the ‘ROLE_‘ prefix is automatically added (if it’s not already there) by any role related method.

So hasAuthority(‘ROLE_ADMIN’) is similar to hasRole(‘ADMIN’) because the ‘ROLE_‘ prefix gets added automatically.

But the good thing about using authorities is that we don’t have to use the ROLE_ prefix at all.

Here’s a quick example where we’re defining users with specific authorities:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
      .withUser("user1").password("user1Pass")
      .authorities("USER")
      .and().withUser("admin").password("adminPass")
      .authorities("ADMIN");
}

We can then of course use these authorities expressions:

@Override
protected void configure(final HttpSecurity http) throws Exception {
    ...
    .antMatchers("/auth/admin/*").hasAuthority("ADMIN")
    .antMatchers("/auth/*").hasAnyAuthority("ADMIN", "USER")
    ...
}

As we can see – we’re not mentioning roles at all here.

Finally – we can of course achieve the same functionality using XML configuration as well:

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="user1" password="user1Pass" authorities="ROLE_USER"/>
            <user name="admin" password="adminPass" authorities="ROLE_ADMIN"/>
        </user-service>
    </authentication-provider>
</authentication-manager>

And:

<http>
    <intercept-url pattern="/auth/admin/*" access="hasAuthority('ADMIN')"/>
    <intercept-url pattern="/auth/*" access="hasAnyAuthority('ADMIN','USER')"/>
</http>

4.3. permitAll, denyAll

Those two annotations are also quite straightforward. We either may permit access to some URL in our service or we may deny access.

Let’s have a look at the example:

...
.antMatchers("/*").permitAll()
...

With this config, we will authorize all users (both anonymous and logged in) to access the page starting with ‘/’ (for example, our homepage).

We can also deny access to our entire URL space:

...
.antMatchers("/*").denyAll()
...

And again, the same config can be done with an XML config as well:

<http auto-config="true" use-expressions="true">
    <intercept-url access="permitAll" pattern="/*" /> <!-- Choose only one -->
    <intercept-url access="denyAll" pattern="/*" /> <!-- Choose only one -->
</http>

4.4. isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticated

In this subsection we focus on expressions related to login status of the user. Let’s start with user that didn’t log in to our page. By specifying following in Java config, we enable all unauthorized users to access our main page:

...
.antMatchers("/*").anonymous()
...

The same in XML config:

<http>
    <intercept-url pattern="/*" access="isAnonymous()"/>
</http>

If we want to secure the website that everybody who uses it will be required to login, we need to use isAuthenticated() method:

...
.antMatchers("/*").authenticated()
...

or XML version:

<http>
    <intercept-url pattern="/*" access="isAuthenticated()"/>
</http>

Moreover, we have two additional expressions, isRememberMe() and isFullyAuthenticated(). Through the use of cookies, Spring enables remember-me capabilities so there is no need to log into the system each time. You can read more about Remember Me here.

In order to give the access to users that were logged in only by remember me function, we may use this:

...
.antMatchers("/*").rememberMe()
...

or XML version:

<http>
    <intercept-url pattern="*" access="isRememberMe()"/>
</http>

Finally, some parts of our services require the user to be authenticated again even if the user is already logged in. For example, user wants to change settings or payment information; it’s of course good practice to ask for manual authentication in the more sensitive areas of the system.

In order to do that, we may specify isFullyAuthenticated(), which returns true if the user is not an anonymous or a remember-me user:

...
.antMatchers("/*").fullyAuthenticated()
...

or the XML version:

<http>
    <intercept-url pattern="*" access="isFullyAuthenticated()"/>
</http>

4.5. principal, authentication

These expressions allow accessing the principal object representing the current authorized (or anonymous) user and the current Authentication object from the SecurityContext, respectively.

We can, for example, use principal to load a user’s email, avatar, or any other data that is accessible in the logged in user.

And authentication provides information about the full Authentication object, along with its granted authorities.

Both are described in further detail in the following article: Retrieve User Information in Spring Security.

4.6. hasPermission APIs

This expression is documented and intended to bridge between the expression system and Spring Security’s ACL system, allowing us to specify authorization constraints on individual domain objects, based on abstract permissions.

Let’s have a look at an example. We have a service that allows cooperative writing articles, with a main editor, deciding which article proposed by other authors should be published.

In order to allow usage of such a service, we may create following methods with access control methods:

@PreAuthorize("hasPermission(#articleId, 'isEditor')")
public void acceptArticle(Article article) {
   …
}

Only authorized user can call this method, and also user needs to have permission isEditor in the service.

We also need to remember to explicitly configure a PermissionEvaluator in our application context:

<global-method-security pre-post-annotations="enabled">
    <expression-handler ref="expressionHandler"/>
</global-method-security>

<bean id="expressionHandler"
    class="org.springframework.security.access.expression
      .method.DefaultMethodSecurityExpressionHandler">
    <property name="permissionEvaluator" ref="customInterfaceImplementation"/>
</bean>

where customInterfaceImplementation will be the class that implements PermissionEvaluator. 

Of course we can also do this with Java configuration as well:

@Override
protected MethodSecurityExpressionHandler expressionHandler() {
    DefaultMethodSecurityExpressionHandler expressionHandler = 
      new DefaultMethodSecurityExpressionHandler();
    expressionHandler.setPermissionEvaluator(new CustomInterfaceImplementation());
    return expressionHandler;
}

5. Conclusion

This tutorial is a comprehensive introduction and guide to Spring Security Expressions.

All examples discussed here are available on the GitHub project.


Quick Guide to Spring MVC with Velocity

$
0
0

The Master Class of "Learn Spring Security" is out:

>> CHECK OUT THE COURSE

1. Introduction

Velocity is a template engine from the Apache Software Foundation that can work with normal text files, SQL, XML, Java code and many other types.

In this article we’re going to focus on utilizing Velocity with a typical Spring MVC web application.

2. Maven Dependencies

Let’s start by enabling the Velocity support – with the following dependencies:

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
</dependency>
		
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-tools</artifactId>
    <version>2.0</version>
</dependency>

The newest versions of both can be found here: velocity and velocity-tools.

3. Configuration

3.1. Web Config

If we don’t want to use an web.xml, let’s configure our web project using Java and an initializer:

public class MainWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext sc) throws ServletException {
        AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
        root.register(WebConfig.class);

        sc.addListener(new ContextLoaderListener(root));

        ServletRegistration.Dynamic appServlet = 
          sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext()));
        appServlet.setLoadOnStartup(1);
    }
}

Alternatively, we can of course use the traditional web.xml:

<web-app ...>
    <display-name>Spring MVC Velocity</display-name>
    <servlet>
        <servlet-name>mvc</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
	    <param-name>contextConfigLocation</param-name>
	    <param-value>/WEB-INF/mvc-servlet.xml</param-value>
	 </init-param>
	 <load-on-startup>1</load-on-startup>
    </servlet>
	
    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
	<url-pattern>/*</url-pattern>
    </servlet-mapping>
 
    <context-param>
        <param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/spring-context.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Notice that we mapped our servlet on the “/*” path.

3.2. Spring Config

Let’s now go over a simple Spring configuration – again, starting with Java:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages= {
  "com.baeldung.mvc.velocity.controller",
  "com.baeldung.mvc.velocity.service" }) 
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
          .addResourceHandler("/resources/**")
          .addResourceLocations("/resources/");
    }
 
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public ViewResolver viewResolver() {
        VelocityLayoutViewResolver bean = new VelocityLayoutViewResolver();
        bean.setCache(true);
        bean.setPrefix("/WEB-INF/views/");
        bean.setLayoutUrl("/WEB-INF/layouts/layout.vm");
        bean.setSuffix(".vm");
        return bean;
    }
    
    @Bean
    public VelocityConfigurer velocityConfig() {
        VelocityConfigurer velocityConfigurer = new VelocityConfigurer();
        velocityConfigurer.setResourceLoaderPath("/");
        return velocityConfigurer;
    }
}

And let’s also have a quick look at the XML version of the configuration:

<beans ...>
    <context:component-scan base-package="com.baeldung.mvc.velocity.*" />
    <context:annotation-config /> 
    <bean id="velocityConfig" 
      class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath">
            <value>/</value>
        </property>
    </bean> 
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
        <property name="cache" value="true" />
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="layoutUrl" value="/WEB-INF/layouts/layout.vm" />
        <property name="suffix" value=".vm" />
    </bean>
</beans>

Here we are telling Spring where to look for annotated bean definitions:

<context:component-scan base-package="com.baeldung.mvc.velocity.*" />

We are indicating we are going to use annotation-driven configuration in our project with the following line: 

<context:annotation-config />

By creating “velocityConfig” and “viewResolver” beans we are telling VelocityConfigurer where to look for templates, and VelocityLayoutViewResolver where to find views and layouts.

4. Velocity Templates

Finally, let’s create our templates – starting with a common header:

<div style="...">
    <div style="float: left">
        <h1>Our tutorials</h1>
    </div>
</div>

and footer:

<div style="...">
    @Copyright baeldung.com
</div>

And let’s define a common layout for our site where we are going to use above fragments with parse in the following code:

<html>
    <head>
        <title>Spring & Velocity</title>  
    </head>
    <body>
        <div>
            #parse("/WEB-INF/fragments/header.vm")
        </div>  
        <div>
            <!-- View index.vm is inserted here -->
            $screen_content
        </div>  
        <div>
            #parse("/WEB-INF/fragments/footer.vm")
        </div>
    </body>
</html>

You can check that $screen_content variable has the content of the pages.

Finally, we’ll create a template for the main content:

<h1>Index</h1>
 
<h2>Tutorials list</h2>
<table border="1">
    <tr>
        <th>Tutorial Id</th>
        <th>Tutorial Title</th>
        <th>Tutorial Description</th>
        <th>Tutorial Author</th>
    </tr>
    #foreach($tut in $tutorials)
    <tr>
        <td>$tut.tutId</td>
        <td>$tut.title</td>
        <td>$tut.description</td>
        <td>$tut.author</td>
    </tr>
    #end
</table>

5. Controller Side

We have created a simple controller which returns a list of tutorials as content for our layout to be populated with:

@Controller
@RequestMapping("/")
public class MainController {
 
    @Autowired
    private ITutorialsService tutService;

    @RequestMapping(value ="/", method = RequestMethod.GET)
    public String defaultPage() {
        return "index";
    }

    @RequestMapping(value ="/list", method = RequestMethod.GET)
    public String listTutorialsPage(Model model) { 
        List<Tutorial> list = tutService.listTutorials();
        model.addAttribute("tutorials", list);
        return "index";
    }
}

Finally, we can access this simple example locally – for example at: localhost:8080/spring-mvc-velocity/

6. Conclusion

In this simple tutorial, we have configured Spring MVC web application with Velocity template engine.

The full sample code for this tutorial can be found in our GitHub repository.

The Master Class of "Learn Spring Security" is out:

>> CHECK OUT THE COURSE

Java Web Weekly, Issue 135

$
0
0

I just released the Master Class of "Learn Spring Security":

>> CHECK OUT THE COURSE

At the very beginning of last year, I decided to track my reading habits and share the best stuff here, on Baeldung. Haven’t missed a review since.

Here we go…

1. Spring and Java

>> Reactive Programming with Spring 5.0 M1 [spring.io]

Reactive support has finally been merged and is included into this cut of the 5.x version of the framework.

If you’ve been holding off from exploring it before, now’s a good time to get your feet wet.

>> Java on Steroids: 5 Super Useful JIT Optimization Techniques [takipi.com]

Interesting notes about what JVM compiler does to optimize the performance of our production code.

>> Java 8 Top Tips [jetbrains.com]

A good read with or without the IntelliJ tips. Of course if you’re using IntelliJ, it’s even better.

>> Oh No, I Forgot Stream::iterate! [codefx.org]

Quick and to the point – some nice APIs are coming along with Java 9.

>> The best way to map a @OneToOne relationship with JPA and Hibernate [vladmihalcea.com]

Hehe, the good ol’ one-to-one relationship.

>> Oracle Paves the Way to Standardise Command Line Options in the JDK [infoq.com]

A quick positive news item slotted for Java 10, among all the negative news about Java EE lately.

Also worth reading:

Webinars and presentations:

Time to upgrade:

2. Technical and Musings

>> DDD Decoded – Don’t Fear Eventual Consistency [sapiensworks.com]

“The only people worried about Eventual Consistency are CRUD programmers”. Priceless.

I could keep quoting, but do yourself a favor and read this one, not only for the technical aspects, but also for the laughs.

>> I wanna go fast: HTTPS’ massive speed advantage [troyhunt.com]

Quite some interesting data here, looking at the speed advantage of HTTP/2.

>> The Business-Personal Value Continuum [daedtech.com]

The writeup explores a tough topic to pin down – the way we approach our work and the balance between our natural need towards craftsmanship and actually putting out work into the world.

I personally strive to keep a healthy tension between the two and, as Sean says – ship when it’s 90% perfect.

>> Logs for SEO [daedtech.com]

A fun read for anyone running any kind of site and dabbling in SEO.

>> 12 great months for Thoughts on Java and some big changes ahead [thoughts-on-java.org]

I always enjoy this kind of post. I think there’s a lot here to unpack and reading through the thought process some else has about a tough life choice is quite helpful. Especially when it deals with such important decisions as – should I quit my job?

Also worth reading:

3. Comics

And my favorite Dilberts of the week:

>> Mordac, the preventer of information services [dilbert.com]

>> What do you do for a living? [dilbert.com]

>> This design would be inefficient [dilbert.com]

4. Pick of the Week

My talk from Spring I/O 2016 came out – if you’re working on REST API and Hypermedia with Spring, let me know what you think:

>> Get HATEOAS and Hypermedia right with Spring [youtube.com]

I just released the Master Class of "Learn Spring Security" Course:

>> CHECK OUT THE COURSE

Introduction to Spring with Akka

$
0
0

The Master Class of "Learn Spring Security" is out:

>> CHECK OUT THE COURSE

1. Introduction

In this article we’ll focus on integrating Akka with the Spring Framework – to allow injection of Spring-based services into Akka actors.

Before reading this article, a prior knowledge of Akka’s basics is recommended.

2. Dependency Injection in Akka

Akka is a powerful application framework based on the Actor concurrency model. The framework is written in Scala which of course makes it fully usable in a Java-based applications as well. And so it’s very often we will want to integrate Akka with an existing Spring-based application or simply use Spring for wiring beans into actors.

The problem with Spring/Akka integration lies in the difference between the management of beans in Spring and the management of actors in Akka: actors have a specific lifecycle that differs from typical Spring bean lifecycle.

Moreover, actors are split into an actor itself (which is an internal implementation detail and cannot be managed by Spring) and an actor reference, which is accessible by a client code, as well as serializable and portable between different Akka runtimes.

Luckily, Akka provides a mechanism, namely Akka extensions, that makes using external dependency injection frameworks a fairly easy task.

3. Maven Dependencies

To demonstrate the usage of Akka in our Spring project, we’ll need a bare minimum Spring dependency — the spring-context library, and also the akka-actor library. The library versions can be extracted to the <properties> section of the pom:

<properties>
    <spring.version>4.3.1.RELEASE</spring.version>
    <akka.version>2.4.8</akka.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>com.typesafe.akka</groupId>
        <artifactId>akka-actor_2.11</artifactId>
        <version>${akka.version}</version>
    </dependency>

</dependencies>

Make sure to check Maven Central for the latest versions of spring-context and akka-actor dependencies.

And notice how, that the akka-actor dependency has a _2.11 postfix in its name, which signifies that this version of Akka framework was built against the Scala version 2.11. The corresponding version of Scala library will be transitively included in your build.

4. Injecting Spring Beans into Akka Actors

Let’s create a simple Spring/Akka application consisting of a single actor that can answer to a person’s name by issuing a greeting to this person. The logic of greeting will be extracted to a separate service. We will want to autowire this service to an actor instance. Spring integration will help us in this task.

4.1. Defining an Actor and a Service

To demonstrate injection of a service into an actor, we’ll create a simple class GreetingActor defined as an untyped actor (extending the Akka’s UntypedActor base class). The main method of every Akka actor is the onReceive method which receives a message and processes it according to some specified logic.

In our case, the GreetingActor implementation checks if the message is of a predefined type Greet, then takes the name of the person from the Greet instance, then uses the GreetingService to receive a greeting for this person and answers sender with the received greeting string. If the message is of some other unknown type, it is passed to the actor’s predefined unhandled method.

Let’s have a look:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class GreetingActor extends UntypedActor {

    private GreetingService greetingService;

    // constructor

    @Override
    public void onReceive(Object message) throws Throwable {
        if (message instanceof Greet) {
            String name = ((Greet) message).getName();
            getSender().tell(greetingService.greet(name), getSelf());
        } else {
            unhandled(message);
        }
    }

    public static class Greet {

        private String name;

        // standard constructors/getters

    }
}

Notice that the Greet message type is defined as a static inner class inside this actor, which is considered a good practice. Accepted message types should be defined as close to an actor as possible to avoid confusion on which message types this actor can process.

Also notice the Spring annotations @Component and @Scope – these define the class as a Spring-managed bean with the prototype scope.

The scope is very important, because every bean retrieval request should result in a newly created instance, as this behavior matches Akka’s actor lifecycle. If you implement this bean with some other scope, the typical case of restarting actors in Akka will most likely function incorrectly.

Finally, notice that we didn’t have to explicitly @Autowire the GreetingService instance — this is possible due to the new feature of Spring 4.3 called Implicit Constructor Injection.

The implementation of GreeterService is pretty straightforward, notice that we defined it as a Spring-managed bean by adding the @Component annotation to it (with default singleton scope):

@Component
public class GreetingService {

    public String greet(String name) {
        return "Hello, " + name;
    }
}

4.2. Adding Spring Support via Akka Extension

The easiest way to integrate Spring with Akka is through an Akka extension.

An extension is a singleton instance created per actor system. It consists of an extension class itself, which implements the marker interface Extension, and an extension id class which usually inherits AbstractExtensionId.

As these two classes are tightly coupled, it makes sense to implement the Extension class nested within the ExtensionId class:

public class SpringExtension 
  extends AbstractExtensionId<SpringExtension.SpringExt> {

    public static final SpringExtension SPRING_EXTENSION_PROVIDER 
      = new SpringExtension();

    @Override
    public SpringExt createExtension(ExtendedActorSystem system) {
        return new SpringExt();
    }

    public static class SpringExt implements Extension {
        private volatile ApplicationContext applicationContext;

        public void initialize(ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }

        public Props props(String actorBeanName) {
            return Props.create(
              SpringActorProducer.class, applicationContext, actorBeanName);
        }
    }
}

FirstSpringExtension implements a single createExtension method from the AbstractExtensionId class – which accounts for creation of an extension instance, the SpringExt object.

The SpringExtension class also has a static field SPRING_EXTENSION_PROVIDER which holds a reference to its only instance. It often makes sense to add a private constructor to explicitly state that SpringExtention is supposed to be a singleton class, but we’ll omit it for clarity.

Secondly, the static inner class SpringExt is the extension itself. As Extension is simply a marker interface, we may define the contents of this class as we see fit.

In our case, we’re going to need the initialize method for keeping a Spring ApplicationContext instance — this method will be called only once per extension’s initialization.

Also we’ll require the props method for creating a Props object. Props instance is a blueprint for an actor, and in our case the Props.create method receives a SpringActorProducer class and constructor arguments for this class. These are the arguments that this class’ constructor will be called with.

The props method will be executed every time we’ll need a Spring-managed actor reference.

The third and last piece of the puzzle is the SpringActorProducer class. It implements Akka’s IndirectActorProducer interface which allows overriding the instantiation process for an actor by implementing the produce and actorClass methods.

As you probably already have guessed, instead of direct instantiation, it will always retrieve an actor instance from the Spring’s ApplicationContext. As we’ve made the actor a prototype-scoped bean, every call to the produce method will return a new instance of the actor:

public class SpringActorProducer implements IndirectActorProducer {

    private ApplicationContext applicationContext;

    private String beanActorName;

    public SpringActorProducer(ApplicationContext applicationContext, 
      String beanActorName) {
        this.applicationContext = applicationContext;
        this.beanActorName = beanActorName;
    }

    @Override
    public Actor produce() {
        return (Actor) applicationContext.getBean(beanActorName);
    }

    @Override
    public Class<? extends Actor> actorClass() {
        return (Class<? extends Actor>) applicationContext
          .getType(beanActorName);
    }
}

4.3. Putting It All Together

The only thing that’s left to do is to create a Spring configuration class (marked with @Configuration annotation) which will tell Spring to scan the current package together with all nested packages (this is ensured by the @ComponentScan annotation) and create a Spring container.

We only need to add a single additional bean — the ActorSystem instance — and initialize the Spring extension on this ActorSystem:

@Configuration
@ComponentScan
public class AppConfiguration {

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public ActorSystem actorSystem() {
        ActorSystem system = ActorSystem.create("akka-spring-demo");
        SPRING_EXTENSION_PROVIDER.get(system)
          .initialize(applicationContext);
        return system;
    }
}

4.4. Retrieving Spring-Wired Actors

To test that everything works correctly, we may inject the ActorSystem instance into our code (either some Spring-managed application code, or a Spring-based test), create a Props object for an actor using our extension, retrieve a reference to an actor via Props object and try to greet somebody:

ActorRef greeter = system.actorOf(SPRING_EXTENSION_PROVIDER.get(system)
  .props("greetingActor"), "greeter");

FiniteDuration duration = FiniteDuration.create(1, TimeUnit.SECONDS);
Timeout timeout = Timeout.durationToTimeout(duration);

Future<Object> result = ask(greeter, new Greet("John"), timeout);

Assert.assertEquals("Hello, John", Await.result(result, duration));

Here we use the typical akka.pattern.Patterns.ask pattern that returns a Scala’s Future instance. Once the computation is completed, the Future is resolved with a value that we returned in our GreetingActor.onMessasge method.

We may either wait for the result by applying the Scala’s Await.result method to the Future, or, more preferably, build the entire application with asynchronous patterns.

5. Conclusion

In this article we’ve showed how to integrate Spring Framework with Akka and autowire beans into actors.

The source code for the article is available on GitHub.

The Master Class of "Learn Spring Security" is out:

>> CHECK OUT THE COURSE

Introduction to AutoValue

$
0
0

1. Overview

AutoValue is a source code generator for Java, and more specifically it’s a library for generating source code for value objects or value-typed objects.

In order to generate a value-type object all you have to do is to annotate an abstract class with the @AutoValue annotation and compile your class. What is generated is a value object with accessor methods, parameterized constructor, properly overridden toString(), equals(Object) and hashCode() methods.

The following code snippet is a quick example of an abstract class that when compiled will result in a value object named AutoValue_Person.

@AutoValue
abstract class Person {
    static Person create(String name, int age) {
        return new AutoValue_Person(name, age);
    }

    abstract String name();
    abstract int age();
}

Let’s continue and find out more about value objects, why we need them and how AutoValue can help make the task of generating and refactoring code much less time consuming.

2. Maven Setup

To use AutoValue in a Maven projects, you need to include the following dependency in the pom.xml:

<dependency>
    <groupId>com.google.auto.value</groupId>
    <artifactId>auto-value</artifactId>
    <version>1.2</version>
</dependency>

The latest version can be found by following this link.

3. Value-Typed Objects

Value-types are the end product of library, so to appreciate its place in our development tasks, we must thoroughly understand value-types, what they are, what they are not and why we need them.

3.1. What are Value-Types?

Value-type objects are objects whose equality to one another is not determined by identity but rather their internal state. This means that two instances of a value-typed object are considered equal as long as they have equal field values.

Typically, value-types are immutable. Their fields must be made final and they must not have setter methods as this will make them changeable after instantiation.

They must consume all field values through a constructor or a factory method.

Value-types are not JavaBeans because they don’t have a default or zero argument constructor and neither do they have setter methods, similarly, they are not Data Transfer Objects nor Plain Old Java Objects.

Additionally, a value-typed class must be final, so that they are not extendable, least that someone overrides the methods. JavaBeans, DTOs and POJOs need not be final.

3.2. Creating a Value-Type

Assuming we want to create a value-type called Foo with fields called text and number. How would we go about it?

We would make a final class and mark all its fields as final. Then we would use the IDE to generate the constructor, the hashCode() method, the equals(Object) method, the getters as mandatory methods and a toString() method, and we would have a class like so:

public final class Foo {
    private final String text;
    private final int number;
    
    public Foo(String text, int number) {
        this.text = text;
        this.number = number;
    }
    
    // standard getters
    
    @Override
    public int hashCode() {
        return Objects.hash(text, number);
    }
    @Override
    public String toString() {
        return "Foo [text=" + text + ", number=" + number + "]";
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        Foo other = (Foo) obj;
        if (number != other.number) return false;
        if (text == null) {
            if (other.text != null) return false;
        } else if (!text.equals(other.text)) {
            return false;
        }
        return true;
    }
}

After creating an instance of Foo, we expect it’s internal state to remain the same for its entire life cycle.

As we will see in a following subsection the hashCode of an object must change from instance to instance, but for value-types, we have to tie it to the fields which define the internal state of the value object.

Therefore, even changing a field of the same object would change the hashCode value.

3.3. How Value-Types Work

The reason value-types must be immutable is to prevent any change to their internal state by the application after they have been instantiated.

Whenever we want to compare any two value-typed objects, we must therefore use the equals(Object) method of the Object class.

This means that we must always override this method in our own value-types and only return true if the fields of the value objects we are comparing have equal values.

Moreover, for us to use our value objects in hash-based collections like HashSets and HashMaps without breaking, we must properly implement the hashCode() method.

3.4. Why we Need Value-Types

The need for value-types comes up quite often. These are cases where we would like to override the default behaviour of the original Object class.

As we already know, the default implementation of the Object class considers two objects equal when they have the same identity however for our purposes we consider two objects equal when they have the same internal state.

Assuming we would like to create a money object as follows:

public class MutableMoney {
    private long amount;
    private String currency;
    
    public MutableMoney(long amount, String currency) {
        this.amount = amount;
        this.currency = currency;
    }
    
    // standard getters and setters
    
}

We can run the following test on it to test it’s equality:

@Test
public void givenTwoSameValueMoneyObjects_whenEqualityTestFails_thenCorrect() {
    MutableMoney m1 = new MutableMoney(10000, "USD");
    MutableMoney m2 = new MutableMoney(10000, "USD");
    assertFalse(m1.equals(m2));
}

Notice the semantics of the test.

We consider it to have passed when the two money objects are not equal. This is because we have not overridden the equals method so equality is measured by comparing the memory references of the objects, which of course are not going to be different, because they are different objects occupying different memory locations.

Each object represents 10,000 USD but Java tells us our money objects are not equal. We want the two objects to test unequal only when either the currency amounts are different or the currency types are different.

Now let us create an equivalent value object and this time we will let the IDE generate most of the code:

public final class ImmutableMoney {
    private final long amount;
    private final String currency;
    
    public ImmutableMoney(long amount, String currency) {
        this.amount = amount;
        this.currency = currency;
    }
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (int) (amount ^ (amount >>> 32));
        result = prime * result	+ ((currency == null) ? 0 : currency.hashCode());
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        ImmutableMoney other = (ImmutableMoney) obj;
        if (amount != other.amount) return false;
        if (currency == null) {
            if (other.currency != null) return false;
        } else if (!currency.equals(other.currency))
            return false;
        return true;
    }
}

The only difference is that we overrode the equals(Object) and hashCode() methods, now we have control over how we want Java to compare our money objects. Let’s run its equivalent test:

@Test
public void givenTwoSameValueMoneyValueObjects_whenEqualityTestPasses_thenCorrect() {
    ImmutableMoney m1 = new ImmutableMoney(10000, "USD");
    ImmutableMoney m2 = new ImmutableMoney(10000, "USD");
    assertTrue(m1.equals(m2));
}

Notice the semantics of this test, we expect it to pass when both money objects test equal via the equals method.

4. Why AutoValue?

Now that we thoroughly understand value-types and why we need them, we can look at AutoValue and how it comes into the equation.

4.1. Issues With Hand-Coding

When we create value-types like we have done in the preceding section, we will run into a number of issues related with bad design and a lot of boilerplate code.

A two field class will have 9 lines of code: one for package declaration, two for the class signature and its closing brace, two for field declarations, two for constructors and its closing brace and two for initializing the fields, but then we need getters for the fields, each taking three more lines of code, making six extra lines.

Overriding the hashCode() and equalTo(Object) methods require about 9 lines and 18 lines respectively and overriding the toString() method adds another five lines.

That means a well-formatted code base for our two field class would take about 50 lines of code.

4.2 IDEs to The Rescue?

This is is easy with an IDE like Eclipse or IntilliJ and with only one or two value-typed classes to create. Think about a multitude of such classes to create, would it still be as easy even if the IDE helps us?

Fast forward, some months down the road, assume we have to revisit our code and make amendments to our Money classes and perhaps convert the currency field from the String type to another value-type called Currency. 

4.3 IDEs not Really so Helpful

An IDE like Eclipse can’t simply edit for us our accessor methods nor the toString(), hashCode() or equals(Object) methods.

This refactoring would have to be done by hand. Editing code increases the potential for bugs and with every new field we add to the Money class, the number of lines increases exponentially.

Recognizing the fact that this scenario happens, that it happens often and in large volumes will make us really appreciate the role of AutoValue.

5. AutoValue Example

The problem AutoValue solves is to take all the boilerplate code that we talked about in the preceding section, out of our way so that we never have to write it, edit it or even read it.

We will look at the very same Money example, but this time with AutoValue. We will call this class AutoValueMoney for the sake of consistency:

@AutoValue
public abstract class AutoValueMoney {
    public abstract String getCurrency();
    public abstract long getAmount();
    
    public static AutoValueMoney create(String currency, long amount) {
        return new AutoValue_AutoValueMoney(currency, amount);
    }
}

What has happened is that we write an abstract class, define abstract accessors for it but no fields, we annotate the class with @AutoValue all totalling to only 8 lines of code,  and javac generates a concrete subclass for us which looks like this:

public final class AutoValue_AutoValueMoney extends AutoValueMoney {
    private final String currency;
    private final long amount;
    
    AutoValue_AutoValueMoney(String currency, long amount) {
        if (currency == null) throw new NullPointerException(currency);
        this.currency = currency;
        this.amount = amount;
    }
    
    // standard getters
    
    @Override
    public int hashCode() {
        int h = 1;
        h *= 1000003;
        h ^= currency.hashCode();
        h *= 1000003;
        h ^= amount;
        return h;
    }
    
    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (o instanceof AutoValueMoney) {
            AutoValueMoney that = (AutoValueMoney) o;
            return (this.currency.equals(that.getCurrency()))
              && (this.amount == that.getAmount());
        }
        return false;
    }
}

We never have to deal with this class directly at all, neither do we have to edit it when we need to add more fields or make changes to our fields like the currency scenario in the previous section.

Javac will always regenerate updated code for us.

While using this new value-type, all callers see is only the parent type as we will see in the following unit tests.

Here is a test that verifies that our fields are being set correctly:

@Test
public void givenValueTypeWithAutoValue_whenFieldsCorrectlySet_thenCorrect() {
    AutoValueMoney m = AutoValueMoney.create("USD", 10000);
    assertEquals(m.getAmount(), 10000);
    assertEquals(m.getCurrency(), "USD");
}

A test to verify that two AutoValueMoney objects with the same currency and same amount test equal follows:

@Test
public void given2EqualValueTypesWithAutoValue_whenEqual_thenCorrect() {
    AutoValueMoney m1 = AutoValueMoney.create("USD", 5000);
    AutoValueMoney m2 = AutoValueMoney.create("USD", 5000);
    assertTrue(m1.equals(m2));
}

When we change the currency type of one money object to GBP, the test: 5000 GBP == 5000 USD is no longer true:

@Test
public void given2DifferentValueTypesWithAutoValue_whenNotEqual_thenCorrect() {
    AutoValueMoney m1 = AutoValueMoney.create("GBP", 5000);
    AutoValueMoney m2 = AutoValueMoney.create("USD", 5000);
    assertFalse(m1.equals(m2));
}

6. AutoValue With Builders

The initial example we have looked at covers the basic usage of AutoValue using a static factory method as our public creation API.

Notice that if all our fields were Strings, it would be easy to interchange them as we passed them to the static factory method, like placing amount in the place of currency and vice versa.

This is especially likely to happen if we have many fields and all are of String type. This problem is made worse by the fact that with AutoValue, all fields are initialized through the constructor.

To solve this problem we should use the builder pattern. Fortunately. this can be generated by AutoValue.

Our AutoValue class does not really change much, except that the static factory method is replaced by a builder:

@AutoValue
public abstract class AutoValueMoneyWithBuilder {
    public abstract String getCurrency();
    public abstract long getAmount();
    static Builder builder() {
        return new AutoValue_AutoValueMoneyWithBuilder.Builder();
    }
    
    @AutoValue.Builder
    abstract static class Builder {
        abstract Builder setCurrency(String currency);
        abstract Builder setAmount(long amount);
        abstract AutoValueMoneyWithBuilder build();
    }
}

The generated class is just the same as the first one but a concrete inner class for the builder is generated as well implementing the abstract methods in the builder:

static final class Builder extends AutoValueMoneyWithBuilder.Builder {
    private String currency;
    private long amount;
    Builder() {
    }
    Builder(AutoValueMoneyWithBuilder source) {
        this.currency = source.getCurrency();
        this.amount = source.getAmount();
    }
    
    @Override
    public AutoValueMoneyWithBuilder.Builder setCurrency(String currency) {
        this.currency = currency;
        return this;
    }
    
    @Override
    public AutoValueMoneyWithBuilder.Builder setAmount(long amount) {
        this.amount = amount;
        return this;
    }
    
    @Override
    public AutoValueMoneyWithBuilder build() {
        String missing = "";
        if (currency == null) {
            missing += " currency";
        }
        if (amount == 0) {
            missing += " amount";
        }
        if (!missing.isEmpty()) {
            throw new IllegalStateException("Missing required properties:" + missing);
        }
        return new AutoValue_AutoValueMoneyWithBuilder(this.currency,this.amount);
    }
}

Notice also how the test results don’t change.

If we want to know that the field values are actually correctly set through the builder, we can execute this test:

@Test
public void givenValueTypeWithBuilder_whenFieldsCorrectlySet_thenCorrect() {
    AutoValueMoneyWithBuilder m = AutoValueMoneyWithBuilder.builder().
      setAmount(5000).setCurrency("USD").build();
    assertEquals(m.getAmount(), 5000);
    assertEquals(m.getCurrency(), "USD");
}

To test that equality depends on internal state:

@Test
public void given2EqualValueTypesWithBuilder_whenEqual_thenCorrect() {
    AutoValueMoneyWithBuilder m1 = AutoValueMoneyWithBuilder.builder()
      .setAmount(5000).setCurrency("USD").build();
    AutoValueMoneyWithBuilder m2 = AutoValueMoneyWithBuilder.builder()
      .setAmount(5000).setCurrency("USD").build();
    assertTrue(m1.equals(m2));
}

And when the field values are different:

@Test
public void given2DifferentValueTypesBuilder_whenNotEqual_thenCorrect() {
    AutoValueMoneyWithBuilder m1 = AutoValueMoneyWithBuilder.builder()
      .setAmount(5000).setCurrency("USD").build();
    AutoValueMoneyWithBuilder m2 = AutoValueMoneyWithBuilder.builder()
      .setAmount(5000).setCurrency("GBP").build();
    assertFalse(m1.equals(m2));
}

7. Conclusion

In this tutorial, we have introduced most of the basics of Google’s AutoValue library and how to use it to create value-type’s with very little code on our part.

An alternative to Google’s AutoValue is the Lombok project – you can have a look at the introductory article about using Lombok here.

The full implementation of all these examples and code snippets can be found in the AutoValue github project.

A Custom Security Expression with Spring Security

$
0
0

The Master Class of "Learn Spring Security" is out:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll focus on creating a custom security expression with Spring Security.

Sometimes, the expressions available in the framework by default are simply not expressive enough. And, in these cases, it’s relatively simple to built up a new expression that is semantically richer than the existing ones.

We’ll first discuss how to create a custom PermissionEvaluator, then a fully custom expression – and finally how to override one of the built-in security expression.

2. A User Entity

First, let’s prepare the foundation for creating the new security expressions.

Let’s have a look at our User entity – which has a Privileges and an Organization:

@Entity
public class User{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false, unique = true)
    private String username;

    private String password;

    @ManyToMany(fetch = FetchType.EAGER) 
    @JoinTable(name = "users_privileges", 
      joinColumns = 
        @JoinColumn(name = "user_id", referencedColumnName = "id"),
      inverseJoinColumns = 
        @JoinColumn(name = "privilege_id", referencedColumnName = "id")) 
    private Set<Privilege> privileges;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "organization_id", referencedColumnName = "id")
    private Organization organization;

    // standard getters and setters
}

And here is our simple Privilege:

@Entity
public class Privilege {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false, unique = true)
    private String name;

    // standard getters and setters
}

And our Organization:

@Entity
public class Organization {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false, unique = true)
    private String name;

    // standard setters and getters
}

Finally – we’ll use a simpler custom Principal:

public class MyUserPrincipal implements UserDetails {

    private User user;

    public MyUserPrincipal(User user) {
        this.user = user;
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        for (Privilege privilege : user.getPrivileges()) {
            authorities.add(new SimpleGrantedAuthority(privilege.getName()));
        }
        return authorities;
    }
    
    ...
}

With all of these classes ready, we’re going to use our custom Principal in a basic UserDetailsService implementation:

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        }
        return new MyUserPrincipal(user);
    }
}

As you can see, there’s nothing complicated about these relationships – the user has one or more privileges, and each user belong to one organization.

3. Data Setup

Next – let’s initialize our database with simple test data:

@Component
public class SetupData {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PrivilegeRepository privilegeRepository;

    @Autowired
    private OrganizationRepository organizationRepository;

    @PostConstruct
    public void init() {
        initPrivileges();
        initOrganizations();
        initUsers();
    }
}

Here is our init methods:

private void initPrivileges() {
    Privilege privilege1 = new Privilege("FOO_READ_PRIVILEGE");
    privilegeRepository.save(privilege1);

    Privilege privilege2 = new Privilege("FOO_WRITE_PRIVILEGE");
    privilegeRepository.save(privilege2);
}
private void initOrganizations() {
    Organization org1 = new Organization("FirstOrg");
    organizationRepository.save(org1);
    
    Organization org2 = new Organization("SecondOrg");
    organizationRepository.save(org2);
}
private void initUsers() {
    Privilege privilege1 = privilegeRepository.findByName("FOO_READ_PRIVILEGE");
    Privilege privilege2 = privilegeRepository.findByName("FOO_WRITE_PRIVILEGE");
    
    User user1 = new User();
    user1.setUsername("john");
    user1.setPassword("123");
    user1.setPrivileges(new HashSet<Privilege>(Arrays.asList(privilege1)));
    user1.setOrganization(organizationRepository.findByName("FirstOrg"));
    userRepository.save(user1);
    
    User user2 = new User();
    user2.setUsername("tom");
    user2.setPassword("111");
    user2.setPrivileges(new HashSet<Privilege>(Arrays.asList(privilege1, privilege2)));
    user2.setOrganization(organizationRepository.findByName("SecondOrg"));
    userRepository.save(user2);
}

Note that:

  • User “john” has only FOO_READ_PRIVILEGE
  • User “tom” has both FOO_READ_PRIVILEGE and FOO_WRITE_PRIVILEGE

4. A Custom Permission Evaluator

At this point we’re ready to start implementing our new expression – through a new, custom permission evaluator.

We are going to use the user’s privileges to secure our methods – but instead of using hard coded privilege names, we want to reach a more open, flexible implementation.

Let’s get started.

4.1. PermissionEvaluator

In order to create our own custom permission evaluator we need to implement the PermissionEvaluator interface:

public class CustomPermissionEvaluator implements PermissionEvaluator {
    @Override
    public boolean hasPermission(
      Authentication auth, Object targetDomainObject, Object permission) {
        if ((auth == null) || (targetDomainObject == null) || !(permission instanceof String)){
            return false;
        }
        String targetType = targetDomainObject.getClass().getSimpleName().toUpperCase();
        
        return hasPrivilege(auth, targetType, permission.toString().toUpperCase());
    }

    @Override
    public boolean hasPermission(
      Authentication auth, Serializable targetId, String targetType, Object permission) {
        if ((auth == null) || (targetType == null) || !(permission instanceof String)) {
            return false;
        }
        return hasPrivilege(auth, targetType.toUpperCase(), 
          permission.toString().toUpperCase());
    }
}

Here is our hasPrivilege() method:

private boolean hasPrivilege(Authentication auth, String targetType, String permission) {
    for (GrantedAuthority grantedAuth : auth.getAuthorities()) {
        if (grantedAuth.getAuthority().startsWith(targetType)) {
            if (grantedAuth.getAuthority().contains(permission)) {
                return true;
            }
        }
    }
    return false;
}

We now have a new security expression available and ready to be used: hasPermission.

And so, instead of using the more hardcoded version:

@PostAuthorize("hasAuthority('FOO_READ_PRIVILEGE')")

We can use use:

@PostAuthorize("hasPermission(returnObject, 'read')")

or

@PreAuthorize("hasPermission(#id, 'Foo', 'read')")

Note: #id refers to method parameter and ‘Foo‘ refers to target object type.

4.2. Method Security Configuration

It’s not enough to define the CustomPermissionEvaluator – we also need to use it in our method security configuration:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = 
          new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
        return expressionHandler;
    }
}

4.3. Example In Practice

Let’s now start making use of the new expression – in a few simple controller methods:

@Controller
public class MainController {
    
    @PostAuthorize("hasPermission(returnObject, 'read')")
    @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}")
    @ResponseBody
    public Foo findById(@PathVariable long id) {
        return new Foo("Sample");
    }

    @PreAuthorize("hasPermission(#foo, 'write')")
    @RequestMapping(method = RequestMethod.POST, value = "/foos")
    @ResponseStatus(HttpStatus.CREATED)
    @ResponseBody
    public Foo create(@RequestBody Foo foo) {
        return foo;
    }
}

And there we go – we’re all set and using the new expression in practice.

4.4. The Live Test 

Let’s now write a simple live tests – hitting the API and making sure everything’s in working order:

@Test
public void givenUserWithReadPrivilegeAndHasPermission_whenGetFooById_thenOK() {
    Response response = givenAuth("john", "123").get("http://localhost:8081/foos/1");
    assertEquals(200, response.getStatusCode());
    assertTrue(response.asString().contains("id"));
}

@Test
public void givenUserWithNoWritePrivilegeAndHasPermission_whenPostFoo_thenForbidden() {
    Response response = givenAuth("john", "123").contentType(MediaType.APPLICATION_JSON_VALUE)
                                                .body(new Foo("sample"))
                                                .post("http://localhost:8081/foos");
    assertEquals(403, response.getStatusCode());
}

@Test
public void givenUserWithWritePrivilegeAndHasPermission_whenPostFoo_thenOk() {
    Response response = givenAuth("tom", "111").contentType(MediaType.APPLICATION_JSON_VALUE)
                                               .body(new Foo("sample"))
                                               .post("http://localhost:8081/foos");
    assertEquals(201, response.getStatusCode());
    assertTrue(response.asString().contains("id"));
}

And here is our givenAuth() method:

private RequestSpecification givenAuth(String username, String password) {
    FormAuthConfig formAuthConfig = 
      new FormAuthConfig("http://localhost:8081/login", "username", "password");
    
    return RestAssured.given().auth().form(username, password, formAuthConfig);
}

5. A New Security Expression

With the previous solution, we were able to define and use the hasPermission expression – which can be quite useful.

However, we’re still somewhat limited here by the name and semantics of the expression itself.

And so, in this section, we’re going to go full custom – and we’re going to implement a security expression called isMember() – checking if the principal is a member of a Organization.

5.1. Custom Method Security Expression

In order to create this new custom expression, we need start by implementing the root note where the evaluation of all security expressions starts:

public class CustomMethodSecurityExpressionRoot 
  extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {

    public CustomMethodSecurityExpressionRoot(Authentication authentication) {
        super(authentication);
    }

    public boolean isMember(Long OrganizationId) {
        User user = ((MyUserPrincipal) this.getPrincipal()).getUser();
        return user.getOrganization().getId().longValue() == OrganizationId.longValue();
    }

    ...
}

Now how we provided this new operation right in the root note here; isMember() is used to check if current user is a member in given Organization.

Also note how we extended the SecurityExpressionRoot to include the built-in expressions as well.

5.2. Custom Expression Handler

Next, we need to inject our CustomMethodSecurityExpressionRoot in our expression handler:

public class CustomMethodSecurityExpressionHandler 
  extends DefaultMethodSecurityExpressionHandler {
    private AuthenticationTrustResolver trustResolver = 
      new AuthenticationTrustResolverImpl();

    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(
      Authentication authentication, MethodInvocation invocation) {
        CustomMethodSecurityExpressionRoot root = 
          new CustomMethodSecurityExpressionRoot(authentication);
        root.setPermissionEvaluator(getPermissionEvaluator());
        root.setTrustResolver(this.trustResolver);
        root.setRoleHierarchy(getRoleHierarchy());
        return root;
    }
}

5.3. Method Security Configuration

Now, we need to use our CustomMethodSecurityExpressionHandler in the method security configuration:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        CustomMethodSecurityExpressionHandler expressionHandler = 
          new CustomMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
        return expressionHandler;
    }
}

5.4. Using the New Expression

Here is a simple example to secure our controller method using isMember():

@PreAuthorize("isMember(#id)")
@RequestMapping(method = RequestMethod.GET, value = "/organizations/{id}")
@ResponseBody
public Organization findOrgById(@PathVariable long id) {
    return organizationRepository.findOne(id);
}

5.5. Live Test

Finally, here is a simple live test for user “john“:

@Test
public void givenUserMemberInOrganization_whenGetOrganization_thenOK() {
    Response response = givenAuth("john", "123").get("http://localhost:8081/organizations/1");
    assertEquals(200, response.getStatusCode());
    assertTrue(response.asString().contains("id"));
}

@Test
public void givenUserMemberNotInOrganization_whenGetOrganization_thenForbidden() {
    Response response = givenAuth("john", "123").get("http://localhost:8081/organizations/2");
    assertEquals(403, response.getStatusCode());
}

6. Disable a Built-in Security Expression

Finally, let’s see how to override a built-in security expression – we’ll discuss disabling hasAuthority().

6.1. Custom Security Expression Root

We’ll start similarly by writing our own SecurityExpressionRoot – mainly because the built-in methods are final and so we can’t override them:

public class MySecurityExpressionRoot implements MethodSecurityExpressionOperations {
    public MySecurityExpressionRoot(Authentication authentication) {
        if (authentication == null) {
            throw new IllegalArgumentException("Authentication object cannot be null");
        }
        this.authentication = authentication;
    }

    @Override
    public final boolean hasAuthority(String authority) {
        throw new RuntimeException("method hasAuthority() not allowed");
    }
    ...
}

After defining this root note, we’ll have to inject it into the expression handler and then wire that handler into our configuration – just as we did above in Section 5.

6.2. Example – Using the Expression

Now, if we want to use hasAuthority() to secure methods – as follows, it will throw RuntimeException when we try to access method:

@PreAuthorize("hasAuthority('FOO_READ_PRIVILEGE')")
@RequestMapping(method = RequestMethod.GET, value = "/foos")
@ResponseBody
public Foo findFooByName(@RequestParam String name) {
    return new Foo(name);
}

6.3. Live Test

Finally, here is our simple test:

@Test
public void givenDisabledSecurityExpression_whenGetFooByName_thenError() {
    Response response = givenAuth("john", "123").get("http://localhost:8081/foos?name=sample");
    assertEquals(500, response.getStatusCode());
    assertTrue(response.asString().contains("method hasAuthority() not allowed"));
}

7. Conclusion

In this guide, we did a deep-dive into the various ways we can implement a custom security expression in Spring Security, if the existing ones aren’t enough.

And, as always, the full source code can be found on GitHub.

The Master Class "Learn Spring Security" is out:

>> CHECK OUT THE COURSE

Viewing all 3703 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>