Thanks to visit codestin.com
Credit goes to www.mscharhag.com

mscharhag, Programming and Stuff;

A blog about programming and software development topics, mostly focused on Java technologies including Java EE, Spring and Grails.

Posts tagged with Java

  • Wednesday, 3 June, 2020

    Java Text Blocks

    Text Blocks are a JDK Enhancement Proposal (JEP 355) available as preview language feature in JDK 13 and 14. It is planned to become a permanent feature in JDK 15. A Text Block is a String literal that spans over multiple lines and avoids the need for most escape sequences.

    Motivation

    Embedding formats like XML, JSON or SQL in standard Java Strings can become quite annoying. For example, a simple snippet of JSON with just two keys is barely readable in Java because of required escaping:

    String json =
            "{\n" +
                "\"name\": \"john\",\n" +
                "\"age\": 42\n" +
            "}";

    Text Blocks for the rescue

    Using the new text blocks feature, we can rewrite our code to this:

    String text = """
            {
                "name": "john",
                "age": "42"
            }
            """;

    Text blocks are opened (and closed) using triple-quotes ("""). The text begins at the next line. After opening a text block, the rest of the line needs to stay empty.

    If we print this string to the console we see:

    {
        "name": "john",
        "age": "42"
    }

    As you might have been noticed, the indentation on the left side has been stripped away. That's because a text block is processed in three steps:

    • Line terminators are normalized to the LF character. This avoids problems between different platforms (like windows and unix).
    • Incidental leading white spaces and all trailing white spaces are removed. Incidental leading white spaces are determined by finding the common number of leading white spaces for all lines.
    • Escape sequences are interpreted. Text blocks can contain the same escape sequences as standard strings (e.g. \t or \n). Note that two new escape sequences have been added: \s for an explicit space and \<eol> as continuation indicator (more on \<eol> later).

    In case we explicitly need leading white spaces we can use the indent() method:

    String text = """
            {
                "name": "john",
                "age": "42"
            }
            """.indent(4);

    This adds 4 additional leading spaces to our JSON snippet. So it looks like this:

        {
            "name": "john",
            "age": "42"
        }
    

    Alternatively we can remove 4 leading spaces from the closing triple-quotes to produce the same result:

    String text = """
            {
                "name": "john",
                "age": "42"
            }
        """; // <-- moving this 4 spaces to the left produces 4 additional leading spaces

    The new \<eol> escape sequence

    With the new \<eol> escape sequence we can split the content of a single line into multiple lines without creating an actual line terminator.

    String text = """
            1
            2 \
            3 \
            4
            5
            """;
    

    Results in:

    1
    2 3 4
    5

    Escaping triple-quotes

    In case we need to write triple-quotes into a text block, only the first quote need to be escaped:

    String text = """
            Java text blocks start with \"""
            """;

    This produces:

    Java text blocks start with """

    Summary

    Text blocks are a nice addition to the Java programming language. They can greatly improve the readability of embedded strings like JSON, XML or SQL by supporting multiple lines a removing the need for double quote escaping.

    Recommended further reading: Text Blocks by Brian Goetz.

    As always you can find all the provided examples on GitHub.

  • Tuesday, 12 May, 2020

    Looking at Java Records

    JEP 359, available as preview feature in JDK 14, introduces records to Java. Records are an easy way to model plain data aggregates.

    A simple Range record looks like this:

    record Range(int from, int to) {}

    A record definition is literally the same as a final class with:

    • immutable fields
    • public accessors
    • a constructor
    • implementations for equals(), hashCode() and toString()

    So we can use our record like this:

    Range range = new Range(1, 5);
    
    int from = range.from(); // 1
    int to = range.to(); // 5
    String toString = range.toString(); // Range[from=1, to=5]
    boolean equals = range.equals(new Range(1, 5)); // true
    

    Note that the accessors are named from() and to() instead of getFrom() and getTo().

    What about constructors?

    Assume we want to add a constructor to our Record to perform some validation:

    record Range(int from, int to) {
        public Range(int from, int to) {
            if (from > to) {
                throw new IllegalArgumentException();
            }
            this.from = from;
            this.to = to;
        }
    }

    This avoids the creation of invalid Range instances. However, it is a bit annoying that we have to write down the from and to fields multiple times to perform a simple validation.

    To avoid this, we can use a special form of constructors for records, called compact constructors. This allows us to skip defining constructor parameters and assigning constructor parameters to fields. It looks like this:

    record Range(int from, int to) {
        public Range {
            if (from > to) {
                throw new IllegalArgumentException();
            }
        }
    }
    

    The result works exactly the same as the previous constructor.

    Custom methods

    We can also add new methods and override existing methods in records.

    For example:

    record Range(int from, int to) {
    
        public int getDistance() {
            return to - from;
        }
    
        @Override
        public String toString() {
            return String.format("Range[from: %s, to: %s, distance: %s]",
                    from, to, getDistance());
        }
    }

    Why are records useful?

    Records simply reduce the amount of code we have to write if we need a simple class to pass data around. Example use cases are multiple return values from a method, compound map keys or data transfer objects.

    Assume you want to find the minimum and maximum value in a collection. With a record you can create a return type for two values with just one line:

    record MinMax(int min, int max) {}
    
    static MinMax minMax(Collection<Integer> numbers) { ... }

    (Yes, you can use separate methods to find the minimum and maximum values. However, then you have to iterate the collection twice)

    Records also provide an easy way to create compound Map keys:

    record NameAndDayOfBirth(String name, LocalDate dob) {}
    
    private Map<NameAndDayOfBirth, Person> entries = ...;

    Summary

    Records provide a less verbose way to create simple data holders. Common use cases are multiple return values, compound map keys or data transfer objects. For more background on records I recommend this writing by Brian Goetz.

    You can find the example code on GitHub.

  • Monday, 20 April, 2020

    Java 14: Looking at the updated switch statement

    JDK 14, released in March 2020, comes with an updated version of the switch statement. This has been a preview feature in JDK 12 and JDK 13.

    To see the difference, let's look at a simple example. Assume we want to compute the daily working time based on a DayOfWeek enum.

    With the old way of using the switch statement, our solution might look like this:

    DayOfWeek day = ...
    float expectedWorkingTime;
    
    switch (day) {
    	case MONDAY:
    	case TUESDAY:
    	case WEDNESDAY:
    	case THURSDAY:
    		expectedWorkingTime = 8f;
    		break;
    	case FRIDAY:
    		expectedWorkingTime = 6f;
    		break;
    	default:
    		expectedWorkingTime = 0f;
    }
    

    With the new switch statement (or expression) we can rewrite our example like this:

    DayOfWeek day = ...
    
    final float expectedWorkingTime = switch (day) {
    	case MONDAY, TUESDAY, WEDNESDAY, THURSDAY -> 8f;
    	case FRIDAY -> 6f;
    	default -> 0f;
    };
    

    So, what's new:

    • The switch keyword can be used as expression and return a value. In this example the value returned by switch is assigned to expectedWorkingTime. Note that this allows us to make expectedWorkingTime final which was not possible in the previous solution.
    • A case statement can contain multiple values, separated by comma.
    • In the case statement, colon is replaced with an arrow (->)
    • When using the arrow (->) syntax, no break keyword is required. If you prefer using break, you can still use the older colon syntax for cases.

    The new yield statement

    In the previous example we return a simple value on the right side of the arrow (->). However, maybe we need to compute this value first, for which we might need a few extra lines of code.

    For example:

    final float expectedWorkingTime = switch (day) {
    	case MONDAY, TUESDAY, WEDNESDAY, THURSDAY -> {
    		if (isFullTimeEmployee) {
    			yield 8;
    		}
    		yield 4;
    	}
    	case FRIDAY -> 6f;
    	default -> 0f;
    };
    

    Here we use a code block in the first case statement to determine the working time. With the new yield statement we return a value from a case block (like using return in methods).

    You can find the examples shown in this post on GitHub.

  • Sunday, 23 February, 2020

    Composing custom annotations with Spring

    Java Annotations were introduced with Java 5 back in 2004 as a way to add meta data into Java source code. Today many major frameworks like Spring (including Spring Boot) or Hibernate heavily rely on annotations.

    In this post we will have a look at a very useful Spring feature which allows us to create our own annotations based on one or more Spring annotations.

    Composing a custom annotation

    Assume we have a set of Spring annotations we often use together. A common example is the combination of @Service and @Transactional:

    @Service
    @Transactional(rollbackFor = Exception.class, timeout = 5)
    public class UserService {
        ...
    }

    Instead of repeating both annotations over and over again, we can create our own annotation containing these two Spring annotations. Creating our own annotation is very easy and looks like this:

    @Service
    @Transactional(rollbackFor = Exception.class, timeout = 5)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyService {}

    An annotation is defined with the @interface keyword (instead of class or interface). The standard Java Annotation @Retention is used to indicate that the annotation should be processable at runtime. We also added both Spring annotations to our annotation.

    Now we can use our own @MyService annotations to annotate our services:

    @MyService
    public class UserService {
        ...
    }

    Spring now detects that @MyService is annotated with @Service and @Transactional and provides the same behaviour as the previous example with both annotations present at the UserService class.

    Note that this is a feature of Spring's way of annotation processing and not a general Java feature. Annotations of other frameworks and libraries might not work if you add them to your own annotation.

    Example use cases

    Custom annotations can be used in various situations to improve the readability of our code. Here are two other examples that might come in handy.

    Maybe we need a property value in various locations of our code. Properties are often injected using Spring's @Value annotation:

    // injects configuration properties my.api.key
    @Value("${my.api.key}") 
    private String apiKey;

    In such a situation we can move the property expression out of our code into a separate annotation:

    @Value("${my.api.key}")
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ApiKey {}

    Within our code we can now use @ApiKey instead of repeating the property expression everywhere:

    @ApiKey
    private String apiKey;

    Another example are integration tests. Within tests often various Spring annotations are used to define the test setup. These annotations can be grouped together using a custom annotation. For example, we can create a @MockMvcTest annotations that defines the Spring setup for mock mvc tests:

    @SpringBootTest
    @AutoConfigureMockMvc(secure = false)
    @TestPropertySource(locations = "classpath:test.properties")
    @ExtendWith(SpringExtension.class)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MockMvcTest {}

    The definition of our tests look a lot cleaner now. We just have to add @MockMvcTest to get the complete test setup:

    @MockMvcTest
    public class MyTest {
    	...
    }

    Note that our @MockMvcTest annotation also contains the @ExtendWith annotation of JUnit 5. Like Spring, JUnit 5 is also able to detect this annotation if it is added to your own custom annotation. Be aware that this will not work if you are still using JUnit 4. With JUnit 4 you have to use @RunWith instead of @ExtendWith. Unfortunatelly @RunWith only works when placed directly at the test class.

    Examples in Spring

    Spring uses this feature in various situations to define shortcuts for common annotations.

    Here are a few examples:

    • @GetMapping is the short version for @RequestMapping(method = {RequestMethod.GET}).
    • @RestController is a composition of @Controller and @ResponseBody.
    • Spring Boots @SpringBootApplication is a shortcut for @SpringBootConfiguration, @EnableAutoConfiguration and @ComponentScan

    You can verify this yourself by looking into the definition of these annotations in Spring's source code.

  • Saturday, 1 February, 2020

    Validating code and architecture constraints with ArchUnit

    Introduction

    ArchUnit is a library for checking Java code against a set of self defined code and architecture constraints. These constraints can be defined in a fluent Java API within unit tests. ArchUnit can be used to validate dependencies between classes or layers, to check for cyclic dependencies and much more. In this post we will create some example rules to see how we can benefit from ArchUnit.

    Required dependency

    To use ArchUnit we need to add the following dependency to our project:

    <dependency>
    	<groupId>com.tngtech.archunit</groupId>
    	<artifactId>archunit-junit5</artifactId>
    	<version>0.13.0</version>
    	<scope>test</scope>
    </dependency>

    If you are still using JUnit 4 you should use the archunit-junit4 artifact instead.

    Creating the first ArchUnit rule

    Now we can start creating our first ArchUnit rule. For this we create a new class in our test folder:

    @RunWith(ArchUnitRunner.class) //only for JUnit 4, not needed with JUnit 5
    @AnalyzeClasses(packages = "com.mscharhag.archunit")
    public class ArchUnitTest {
    
        // verify that classes whose name name ends with "Service" should be located in a "service" package
        @ArchTest
        private final ArchRule services_are_located_in_service_package = classes()
                .that().haveSimpleNameEndingWith("Service")
                .should().resideInAPackage("..service");
    }

    With @AnalyzeClasses we tell ArchUnit which Java packages should be analyzed. If you are using JUnit 4 you also need to add the ArchUnit JUnit runner.

    Inside the class we create a field and annotate it with @ArchTest. This is our first test.

    We can define the constraint we want to validate by using ArchUnits fluent Java API. In this example we want to validate that all classes whose name ends with Service (e.g. UserService) are located in a package named service (e.g. foo.bar.service).

    Most ArchUnit rules start with a selector that indicates what type of code units should be validated (classes, methods, fields, etc.). Here, we use the static method classes() to select classes. We restrict the selection to a subset of classes using the that() method (here we only select classes whose name ends with Service). With the should() method we define the constraint that should be matched against the selected classes (here: the classes should reside in a service package).

    When running this test class all tests annotated with @ArchTest will be executed. The test will fail, if ArchUnits detects service classes outside a service package.

    More examples

    Let's look at some more examples.

    We can use ArchUnit to make sure that all Logger fields are private, static and final:

    // verify that logger fields are private, static and final
    @ArchTest
    private final ArchRule loggers_should_be_private_static_final = fields()
            .that().haveRawType(Logger.class)
            .should().bePrivate()
            .andShould().beStatic()
            .andShould().beFinal();
    

    Here we select fields of type Logger and define multiple constraints in one rule.

    Or we can make sure that methods in utility classes have to be static:

    // methods in classes whose name ends with "Util" should be static
    @ArchTest
    static final ArchRule utility_methods_should_be_static = methods()
            .that().areDeclaredInClassesThat().haveSimpleNameEndingWith("Util")
            .should().beStatic();

    To enforce that packages named impl contain no interfaces we can use the following rule:

    // verify that interfaces are not located in implementation packages
    @ArchTest
    static final ArchRule interfaces_should_not_be_placed_in_impl_packages = noClasses()
            .that().resideInAPackage("..impl..")
            .should().beInterfaces();

    Note that we use noClasses() instead of classes() to negate the should constraint.

    (Personally I think this rule would be much easier to read if we could define the rule as interfaces().should().notResideInAPackage("..impl.."). Unfortunately ArchUnit provides no interfaces() method)

    Or maybe we are using the Java Persistence API and want to make sure that EntityManager is only used in repository classes:

    @ArchTest
    static final ArchRule only_repositories_should_use_entityManager = noClasses()
            .that().resideOutsideOfPackage("..repository")
            .should().dependOnClassesThat().areAssignableTo(EntityManager.class);

    Layered architecture example

    ArchUnit also comes with some utilities to validate specific architecture styles.

    For example can we use layeredArchitecture() to validate access rules for layers in a layered architecture:

    @ArchTest
    static final ArchRule layer_dependencies_are_respected = layeredArchitecture()
            .layer("Controllers").definedBy("com.mscharhag.archunit.layers.controller..")
            .layer("Services").definedBy("com.mscharhag.archunit.layers.service..")
            .layer("Repositories").definedBy("com.mscharhag.archunit.layers.repository..")
            .whereLayer("Controllers").mayNotBeAccessedByAnyLayer()
            .whereLayer("Services").mayOnlyBeAccessedByLayers("Controllers")
            .whereLayer("Repositories").mayOnlyBeAccessedByLayers("Services");

    Here we define three layers: Controllers, Services and Repositories. The repository layer may only accessed by the service layer while the service layer may only be accessed by controllers.

    Shortcuts for common rules

    To avoid that we have to define all rules our self, ArchUnit comes with a set of common rules defined as static constants. If these rules fit our needs, we can simply assign them to @ArchTest fields in our test.

    For example we can use the predefined NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS rule if we make sure no exceptions of type Exception and RuntimeException are thrown:

    @ArchTest
    private final ArchRule no_generic_exceptions = NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS;

    Summary

    ArchUnit is a powerful tool to validate a code base against a set of self defined rules. Some of the examples we have seen are also reported by common static code analysis tools like FindBugs or SonarQube. However, these tools are typically harder to extend with your own project specific rules and this is where ArchUnit comes in.

    As always you can find the Sources from the examples on GitHub. If you are interested in ArchUnit you should also check the comprehensive user guide.

  • Thursday, 23 January, 2020

    Creating an API Gateway with Zuul and Spring Boot

    Introduction

    When working with micro services it is common to have unified access-point to your system (also called API Gateway). Consumers only talk with the API Gateway and not with the services directly. This hides the fact that your system is composed out of multiple smaller services. The API Gateway also helps solving common challenges like authentication, managing cross-origin resource sharing (CORS) or request throttling.

    Zuul is a JVM-based API Gateway developed and open-sourced by Netflix. In this post we will create a small Spring application that includes a zuul proxy for routing requests to other services.

    Enabling zuul proxy

    To use zuul in a project we have to add the spring-cloud-starter-netflix-zuul dependency. If we want to use the spring zuul actuator endpoint (more on this later), we also need to add the spring-boot-starter-actuator dependency.

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    
    <!-- optional -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    Next we have to enable the zuul proxy using @EnableZuulProxy in our spring boot application class (or any other spring @Configuration class)

    @SpringBootApplication
    @EnableZuulProxy
    public class ZuulDemoApplication {
        ...
    }
    

    Now we can start configuring our routes.

    Configuring routes

    Routes describe how incoming requests should be routed by zuul. To configure zuul routes we only have to add a few lines to our spring boot application.yml (or application.properties) file:

    application.yml:

    zuul:
      routes:
        users:
          path: /users/**
          url: https://users.myapi.com
        projects:
          path: /projects/**
          url: https://projects.myapi.com
    

    Here we define the routes for two endpoints: /users and /projects: Requests to /users will be routed to https://users.myapi.com while requests to /projects are routed to https://projects.myapi.com.

    Assume we start this example application locally and send a GET request to http://localhost:8080/users/john. This request matches the zuul route /users/** so zuul will forward the request to https://users.myapi.com/john.

    When using a service registry (like Eureka) we can alternatively configure a service id instead of an url:

    zuul:
      routes:
        users:
          path: /users/**
          serviceId: user_service
    

    Another useful option is sensitiveHeaders, which allows us to remove headers before the request is routed to another service. This can be used to avoid leaking of sensitive headers into external servers (e.g. security tokens or session ids).

    zuul:
      routes:
        users:
          path: /users/**
          url: https://users.myapi.com      
          sensitiveHeaders: Cookie,Set-Cookie,Authorization
    

    Note that the shown example headers (Cookie,Set-Cookie,Authorization) are the default value of the sensitiveHeaders property. So these headers will not be passed, even if sensitiveHeaders is not specified.

    Request / Response modification with filters

    We can customize zuul routing using filters. To create a zuul filter we create a new spring bean (marked with @Component) which extends from ZuulFilter:

    @Component
    public class MyFilter extends ZuulFilter {
    
        @Override
        public String filterType() {
            return FilterConstants.PRE_TYPE;
        }
    
        @Override
        public int filterOrder() {
            return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
        }
    
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        @Override
        public Object run() {
            RequestContext context = RequestContext.getCurrentContext();
            context.addZuulRequestHeader("my-auth-token", "s3cret");
            return null;
        }
    }
    

    ZuulFilter requires the definition of four methods:

    • Within filterType() we define that our filter should run before (PRE_TYPE) the actual routing. If we want to modify the response of the service before it is send back to the client, we can return POST_TYPE here.
    • With filterOrder() we can influence to order of filter execution
    • shouldFilter() indicates if this filter should be executed (= calling the run() method)
    • in run() we define the actual filter logic. Here we add a simple header named my-auth-token to the request that is routed to another service.

    Filters allow us to modify the request before it is send to the specified service or to modify the response of the service before it is send back to the client.

    Actuator endpoint

    Spring cloud zuul exposed an additional Spring Boot actuator endpoint. To use this feature we need to have spring-boot-starter-actuator in the classpath.

    By default the actuator endpoint is disabled. Within application.yml we enable specific actuator endpoints using the management.endpoints.web.exposure.include property:

    management:
      endpoints:
        web:
          exposure:
            include: '*'
    

    Here we simply enable all actuator endpoints. More detailed configuration options can be found in the Spring Boot actuator documentation.

    After enabling the zuul actuator endpoint we can send a GET request to http://localhost:8080/actuator/routes to get a list of all configured routes.

    An example response might look like this:

    {
        "/users/**":"https://users.myapi.com",
        "/projects/**":"project_service"
    }
    

    Summary

    With Spring cloud you can easliy integrate a zuul proxy in your application. This allows you the configuration of routes in .yml or .properties files. Routing behaviour can be customized with Filters.

    More details on spring's support for zuul can be found in the official spring cloud zuul documentation. As always you can find the examples shown in this post on GitHub.