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

Introduction to Spring Boot CLI

$
0
0

1. Introduction

Spring Boot CLI is a command-line abstraction that allows us to easily run Spring micro-services expressed as Groovy scripts. It also provides simplified and enhanced dependency management for those services.

This short article takes a quick look at how to configure Spring Boot CLI and execute simple terminal commands to run pre-configured micro-services.

We’ll use Spring Boot CLI 2.0.0.RELEASE for this article. The newest version of Spring Boot CLI can be found over at Maven Central.

2. Setting Up Spring Boot CLI

One of the easiest ways to set up Spring Boot CLI is to use SDKMAN. Setup and installation instructions for SDKMAN can be found here.

After installing SDKMAN, run the following command to automatically install and configure Spring Boot CLI:

$ sdk install springboot

To verify the install, run the command:

$ spring --version

We can also install Spring Boot CLI by compiling from source, and Mac users can use pre-built packages from Homebrew or MacPorts. See the official docs for all installation options.

3. Common Terminal Commands

Spring Boot CLI provides several useful commands and features out-of-the-box. One of the most helpful features is Spring Shell, which wraps commands with the necessary spring prefix.

To start the embedded shell, we run:

spring shell

From here, we can directly enter desired commands without pre-pending the spring keyword (since we’re now in spring shell).

For example, we can display the current version of the running CLI by typing:

version

One of the most important commands is telling Spring Boot CLI to run a Groovy script:

run [SCRIPT_NAME].groovy

Spring Boot CLI will either automatically infer the dependencies or will do so given the correctly supplied annotations. After this, it will launch an embedded web container and app.

Let’s take a closer look at how to use Groovy script with Spring Boot CLI!

4. Essential Groovy Scripts

Groovy and Spring come together with Spring Boot CLI to allow powerful, performant micro-services to be quickly scripted in single-file Groovy deployments.

Support for multiply-scripted applications usually requires additional build tools like Maven or Gradle.

Below we’ll cover some of the most common use-cases for Spring Boot CLI, reserving more complex setups for other articles.

For a list of all Spring-supported Groovy annotations, please check out the official docs.

4.1. @Grab

The @Grab annotation and Groovy’s Java-esque import clauses allow for easy dependency management and injection.

In fact, most annotations abstract, simplify, and automatically include the necessary import statements. This allows us to spend more time thinking about architecture and the underlying logic of the services we want to deploy.

Let’s take a look at how to use the @Grab annotation:

package org.test

@Grab("spring-boot-starter-actuator")

@RestController
class ExampleRestController{
  //...
}

As we can see, spring-boot-starter-actuator comes pre-configured allowing for succinct script deployment without requiring customized application or environmental properties, XML, or other programmatic configuration, though each of those things can be specified when necessary.

The full list of @Grab arguments — each specifying a library to download and import — is available here.

4.2. @Controller, @RestController, and @EnableWebMvc

To further expedite deployment, we can alternatively utilize Spring Boot CLI’s provided “grab hints” to automatically infer correct dependencies to import.

We’ll go over some of the most common use cases below.

For example, we can use the familiar @Controller and @Service annotations to quickly scaffold a standard MVC controller and service:

@RestController
class Example {
 
    @Autowired
    private MyService myService;

    @GetMapping("/")
    public String helloWorld() {
        return myService.sayWorld();
    }
}

@Service
class MyService {
    public String sayWorld() {
        return "World!";
    }
}

Spring Boot CLI supports all default configuration for Spring Boot. So, we can our Groovy apps will automatically access static resources from their usual default locations.

4.3. @EnableWebSecurity

To add Spring Boot Security options to our app, we can use the @EnableWebSecurity annotation, which will then be automatically downloaded by Spring Boot CLI.

Below, we’ll abstract part of this process using the spring-boot-starter-security dependency, which leverages the @EnableWebSecurity annotation under the hood:

package bael.security

@Grab("spring-boot-starter-security")

@RestController
class SampleController {

    @RequestMapping("/")
    public def example() {
        [message: "Hello World!"]
    }
}

For more details on how to protect resources and handle security, please check out the official documentation.

4.4. @Test

To set up a simple JUnit test, we can add the @Grab(‘junit’) or @Test annotations:

package bael.test

@Grab('junit')
class Test {
    //...
}

This will allow us to execute JUnit tests easily.

4.5. DataSource and JdbcTemplate 

Persistent data options can be specified including DataSource or JdbcTemplate without explicitly using the @Grab annotation:

package bael.data

@Grab('h2')
@Configuration
@EnableWebMvc
@ComponentScan('bael.data')
class DataConfig {

    @Bean
    DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
          .setType(EmbeddedDatabaseType.H2).build();
    }

}

By simply using familiar Spring bean configuration conventions, we’ve grabbed the H2 embedded database and set it as the DataSource.

5. Custom Configuration

There are two primary ways to configure a Spring Boot micro-service using Spring Boot CLI:

  1. we can add argument parameters to our terminal commands
  2. we can use a customized YAML file to provide an application configuration

Spring Boot will automatically search the /config directory for application.yml or application.properties

├── app
    ├── app.groovy
    ├── config
        ├── application.yml
    ...

We can also set up:

├── app
    ├── example.groovy
    ├── example.yml
    ...

A full list of application properties can be found here at Spring.

6. Conclusion

This concludes our quick walk-through of Spring Boot CLI! For more details, check out the official docs.

And as usual, the source code for this article can be found over on GitHub.


A Guide to the JSTL Library

$
0
0

1. Overview

JavaServer Pages Tag Library (JSTL) is a set of tags that can be used for implementing some common operations such as looping, conditional formatting, and others.

In this tutorial, we’ll be discussing how to setup JSTL and how to use its numerous tags.

2. Setup

To enable JSTL features, we’d have to add the library to our project. For a Maven project, we add the dependency in pom.xml file:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

With the library added to our project, the final setup will be to add the core JSTL tag and any other tags’ namespace file to our JSP using the taglib directive like this:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

Next, we’ll take a look at these tags which are broadly grouped into five categories.

3. Core Tags

JSTL core tag library contains tags for performing basic operations such as printing values, variables declaration, exception handling, performing iterations, and declaring conditional statements among others.

Let’s have a look at core tags.

3.1. The <c:out> Tag

<c:out> is used for displaying values contained in variables or the result of an implicit expression.

It has three attributes: value, default, and escapeXML. The escapeXML attribute outputs raw XML tags contained in the value attribute or its enclosure.

An example of <c:out> tag will be:

<c:out value="${pageTitle}"/>

3.2. The <c:set> Tag

The <c:set> tag is used for declaring scoped variables in JSP. We can also declare the name of the variable and its value in the var and value attributes respectively.

An example will be of the form:

<c:set value="JSTL Core Tags Example" var="pageTitle"/>

3.3. The <c:remove> Tag

The <c:remove> tag removes scoped variables which is equivalent to assigning null to a variable. It takes var and scope attribute with scope having a default value of all scopes.

Below, we show an example usage of <c:remove> tag:

<c:remove var="pageTitle"/>

3.4. The <c:catch> Tag

The <c:catch> tag catches any exception thrown within its enclosure. If the exception is thrown, it’s value is stored in the var attribute of this tag.

Typical usage could look like:

<c:catch var ="exceptionThrown">
    <% int x = Integer.valueOf("a");%>
</c:catch>

And to check if the exception is thrown, we use the <c:if> tag as shown below:

<c:if test = "${exceptionThrown != null}">
    <p>The exception is : ${exceptionThrown} <br />
      There is an exception: ${exceptionThrown.message}
    </p>
</c:if>

3.5. The <c:if> Tag

The <c:if> is a conditional tag that displays or executes it’s enclosed scriptlets only when its test attribute evaluates to true. The result of the evaluation can be stored in its var attribute.

3.6. <c:choose>, <c:when> and <c:otherwise> Tags

The <c:choose> is a parent tag that is used in performing switch-like or if-else expressions. It has two subtags; <c:when> and <c:otherwise> which represent if/else-if and else respectively.

<c:when> takes a test attribute which holds the expression to be evaluated. Below, we show an example usage of these tags:

<c:set value="<%= Calendar.getInstance().get(Calendar.SECOND)%>" var="seconds"/>
<c:choose>
    <c:when test="${seconds le 30 }">
        <c:out value="${seconds} is less than 30"/>
    </c:when>
    <c:when test="${seconds eq 30 }">
        <c:out value="${seconds} is equal to 30"/>
    </c:when>
    <c:otherwise>
        <c:out value="${seconds} is greater than 30"/>
    </c:otherwise>
</c:choose>

3.7. The <c:import> Tag

The <c:import> tag handles fetching and exposing content from absolute or relative URLs.

We can use the url and var attributes to hold the URL, and the content fetched from the URL respectively. For example, we could import contents from a URL by:

<c:import var = "data" url = "http://www.example.com"/>

3.8. The <c:forEach> Tag

The <c:forEach> tag is similar to Java’s for, while or do-while syntax. The items attribute holds the list of items to be iterated over, while begin and end attributes hold the starting and ending index respectively (zero indexing).

<c:forEach> tag also has a step attribute that controls the size of index increment after each iteration. Below, we show an example usage:

<c:forEach var = "i" items="1,4,5,6,7,8,9">
    Item <c:out value = "No. ${i}"/><p>
</c:forEach>

3.9. The <c:forTokens> Tag

The <c:forTokens> tag is used for splitting a String into tokens and iterating through them.

Similar to <c:forEach> tag, it has an items attribute and an additional delim attribute which is the delimiter for the String like this:

<c:forTokens 
  items = "Patrick:Wilson:Ibrahima:Chris" 
  delims = ":" var = "name">
    <c:out value = "Name: ${name}"/><p>
</c:forTokens>

3.10. <c:url> and <c:param> Tags

The <c:url> tag is useful for formatting a URL with proper request encoding. the formatted URL is stored in the var attribute.

<c:url> tag also has a <c:param> subtag which is used for specifying URL parameters. We show an example below:

<c:url value = "/core_tags" var = "myURL">
    <c:param name = "parameter_1" value = "1234"/>
    <c:param name = "parameter_2" value = "abcd"/>
</c:url>

3.11. The <c:redirect> Tag

The <c:redirect> tag performs a URL rewrite and redirects the user to the page specified in its url attribute. A typical use case will look like this:

<c:redirect url="/core_tags"/>

4. Formatting Tags

JSTL formatting tag library provides a convenient way for formatting text, numbers, dates, times and other variables for better display.

JSTL formatting tags can also be used to enhance the internationalization of a website.

Before using these formatting tags, we’ve to add the taglib to our JSP:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

Let’s identify the various formatting tags and how they can be used.

4.1. The <fmt:formatDate> Tag

The <fmt:formatDate> tag is useful in formatting dates or time. The value attribute holds the date to be formatted, and the type attribute takes one of three values; date, time or both.

<fmt:formatDate> also has a pattern attribute where we can specify the desired formatting pattern. Below is an example of one of the patterns:

<c:set var="now" value="<%= new java.util.Date()%>"/>
<fmt:formatDate type="time" value="${now}"/>

4.2. The <fmt:parseDate> Tag

The <fmt:parseDate> tag is similar to <fmt:formatDate> tag.

The difference is that with <fmt:parseDate> tag we can specify the formatting pattern that the underlying date parser should expect the date value to be in.

We can parse dates:

<c:set var="today" value="28-03-2018"/>
<fmt:parseDate value="${today}" var="parsedDate" pattern="dd-MM-yyyy"/>

4.3. The <fmt:formatNumber> Tag

The <fmt:formatNumber> tag handles rendering of numbers in a specific pattern or precision which can be one of number, currency or percentage as specified in its type attribute. An example usage of <fmt:formatNumber> would be:

<c:set var="fee" value="35050.1067"/>
<fmt:formatNumber value="${fee}" type="currency"/>

4.4. The <fmt:parseNumber> Tag

The <fmt:parseNumber> tag is similar to <fmt:formatNumber> tag. The difference is that with <fmt:parseNumber> tag we can specify the formatting pattern that the underlying number parser should expect the number to be in.

We could use this like:

<fmt:parseNumber var="i" type="number" value="${fee}"/>

4.5. The <fmt:bundle> Tag

The <fmt:bundle> tag is a parent tag for <fmt:message> tag. <fmt:bundle> makes the bundle specified in its basename attribute to the enclosed <fmt:message> tags.

<fmt:bundle> tag is useful for enabling internationalization as we can specify locale-specific objects. Typical usage will be of the form:

<fmt:bundle basename="com.baeldung.jstl.bundles.CustomMessage" prefix="verb.">
    <fmt:message key="go"/><br/>
    <fmt:message key="come"/><br/>
    <fmt:message key="sit"/><br/>
    <fmt:message key="stand"/><br/>
</fmt:bundle>

4.6. The <fmt:setBundle> Tag

The <fmt:setBundle> tag is used for loading a resource bundle within JSP and making it available through the entire page. The loaded resource bundle is stored in the var attribute of the <fmt:setBundle> tag. We can set bundle by:

<fmt:setBundle basename="com.baeldung.jstl.bundles.CustomMessage" var="lang"/>

4.7. The <fmt:setLocale> Tag

The <fmt:setLocale> tag is used to set the locale for the sections in JSP placed after it’s declaration. Typically we will set this by:

<fmt:setLocale value="fr_FR"/>

fr_FR represents the locale which is French in this case.

4.8. The <fmt:timeZone> Tag

The <fmt:timeZone> tag is a parent tag that specifies the time zone to be used by any time formatting or parsing actions by tags in its enclosure.

This time zone parameter is supplied by its value attribute. An example usage is shown below:

<fmt:timeZone value="${zone}">
    <fmt:formatDate value="${now}" timeZone="${zn}" 
      type="both"/>
</fmt:timeZone>

4.9. The <fmt:setTimeZone> Tag

The <fmt:setTimeZone> tag can be used to copy the time zone specified in its value attribute to a scoped variable specified in its var attribute. We define this by:

<fmt:setTimeZone value="GMT+9"/>

4.10. The <fmt:message> Tag

The <fmt:message> tag is used to display internationalization message. The unique identifier for the message to be retrieved should be passed to its key attribute.

A specific bundle to lookup the message which can also be specified through the bundle attribute.

This may look like this:

<fmt:setBundle basename = "com.baeldung.jstl.bundles.CustomMessage" var = "lang"/>
<fmt:message key="verb.go" bundle="${lang}"/>

4.11. The <fmt:requestEncoding> Tag

The <fmt:requestEncoding> tag is useful in specifying the encoding type for forms with an action type of post.

The name of the character encoding to use is supplied through the key attribute of the <fmt:requestEncoding> tag.

Let’s see an example below:

<fmt:requestEncoding value = "UTF-8" />

5. XML Tags

JSTL XML tag library provides convenient ways for interacting with XML data within a JSP.

To be able to access these XML tags, we’d add the tag library to our JSP by:

<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>

Let’s look at the different tags in the JSTL XML tags library.

5.1. The <x:out> Tag

The <x:out> tag is similar to <%= %> scriptlet tag in JSP but <x:out> is specifically used for XPath expressions.

<x:out> tag has a select and escapeXML attributes used for specifying the XPath expression to evaluate a String and to enable escaping of special XML characters respectively.

A simple example is:

<x:out select="$output/items/item[1]/name"/>

$output in the above refers to a preloaded XSL file.

5.2. The <x:parse> Tag

The <x:parse> tag is used for parsing the XML data specified in its xml or doc  attribute or enclosure. A typical example would be:

<x:parse xml="${xmltext}" var="output"/>

5.3. The <x:set> Tag

The <x:set> tag sets the variable specified in its var attribute to the evaluated XPath expression passed to its select attribute. A typical example would be:

<x:set var="fragment" select="$output//item"/>

5.4. The <x:if> Tag

The <x:if> tag processes its body if the XPath expression supplied to its select attribute evaluates to true.

The result of the evaluation can be stored in its var attribute.

A simple use case will look like:

<x:if select="$output//item">
    Document has at least one <item> element.
</x:if>

5.5. The <x:forEach> Tag

The <x:forEach> tag is used for looping over nodes in an XML document. The XML document is supplied through <x:forEach> tag’s select attribute.

Just like the <c:forEach> core tag, <x:forEach> tag has begin, end  and step attributes.

Thus, we’d have:

<ul class="items">
    <x:forEach select="$output/items/item/name" var="item">
        <li>Item Name: <x:out select="$item"/></li>
    </x:forEach>
</ul>

5.6. <x:choose>, <x:when> and <x:otherwise> Tags

The <x:choose> tag is a parent tag that is used in performing switch-like or if/else-if/else expressions and has no attributes but encloses <x:when> and <x:otherwise> tags.

<x:when> tag is similar if/else-if and takes a select attribute which holds the expression to be evaluated.

<x:otherwise> tag is similar to else/default clause and has no attribute.

Below, we show a sample use case:

<x:choose>
    <x:when select="$output//item/category = 'Sneakers'">
        Item category is Sneakers
    </x:when>
    <x:when select="$output//item/category = 'Heels'">
        Item category is Heels
    </x:when>
    <x:otherwise>
       Unknown category.
    </x:otherwise>
</x:choose>

5.7. <x:transform> and <x:param> Tags

The <x:transform> tag transforms an XML document within JSP by applying an eXtensible Stylesheet Language (XSL) to it.

The XML document or String to be transformed is supplied to the doc attribute while the XSL to be applied is passed to the xslt attribute of the <x:transform> tag.

<x:param> tag is a subtag of <x:transform> tag and it is used to set a parameter in the transformation stylesheet.

A simple use case will be of the form:

<c:import url="/items_xml" var="xslt"/>
<x:transform xml="${xmltext}" xslt="${xslt}">
    <x:param name="bgColor" value="blue"/>
</x:transform>

6. SQL Tags

JSTL SQL tag library provides tags for performing relational database operations.

To enable JSTL SQL tags, we add the taglib to our JSP:

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

JSTL SQL tags support different databases including MySQL, Oracle and Microsoft SQL Server.

Next, we’ll look at the different SQL tags available.

6.1. The <sql:setDataSource> Tag

The <sql:setDataSource> tag is used for defining the JDBC configuration variables.

These configuration variables are held in the driver, url, user, password and dataSource  attributes of the <sql:setDataSource> tag as shown below:

<sql:setDataSource var="dataSource" driver="com.mysql.cj.jdbc.Driver"
  url="jdbc:mysql://localhost/test" user="root" password=""/>

In the above, the var attribute holds a value that identifies the associated database.

6.2. The <sql:query> Tag

The <sql:query> tag is used to execute an SQL SELECT statement with the result stored in a scoped variable defined in its var attribute. Typically, we’d define this as:

<sql:query dataSource="${dataSource}" var="result">
    SELECT * from USERS;
</sql:query>

<sql:query> tag’s sql attribute holds the SQL command to be executed. Other attributes include maxRows, startRow, and dataSource.

6.3. The <sql:update> Tag

The <sql:update> tag is similar to <sql:query> tag but executes only SQL INSERT, UPDATE or DELETE operations which do not require a return value.

An example usage would be:

<sql:update dataSource="${dataSource}" var="count">
    INSERT INTO USERS(first_name, last_name, email) VALUES
      ('Grace', 'Adams', 'gracea@domain.com');
</sql:update>

<sql:update> tag’s var attribute holds the number of rows that were affected by the SQL statement specified in its sql attribute.

6.4. The <sql:param> Tag

The <sql:param> tag is a sub tag that can be used within <sql:query> or <sql:update> tag to supply a value for a value placeholder in the sql statement as this:

<sql:update dataSource = "${dataSource}" var = "count">
    DELETE FROM USERS WHERE email = ?
    <sql:param value = "gracea@domain.com" />
</sql:update>

<sql:param> tag has a single attribute; value which holds the value to be supplied.

6.5. The <sql:dateParam> Tag

The <sql:dateParam> tag is used within <sql:query> or <sql:update> tag to supply a date and time value for a value placeholder in the sql statement.

We can define this in our JSP like this:

<sql:update dataSource = "${dataSource}" var = "count">
    UPDATE Users SET registered = ? WHERE email = ?
    <sql:dateParam value = "<%=registered%>" type = "DATE" />
    <sql:param value = "<%=email%>" />
</sql:update>

Like the <sql:param> tag, <sql:dateParam> tag has a value attribute with an additional type attribute whose value can be one of date, time or timestamp (date and time).

6.6. The <sql:transaction> Tag

The <sql:transaction> tag is used to create JDBC transaction-like operation by grouping <sql:query> and <sql:update> tags together like this:

<sql:transaction dataSource = "${dataSource}">
    <sql:update var = "count">
        UPDATE Users SET first_name = 'Patrick-Ellis' WHERE
          email='patrick@baeldung.com'
    </sql:update>
    <sql:update var = "count">
        UPDATE Users SET last_name = 'Nelson' WHERE 
          email ='patrick@baeldung.com'
    </sql:update>
    <sql:update var = "count">
        INSERT INTO Users(first_name, last_name, email) 
          VALUES ('Grace', 'Adams', 'gracea@domain.com');
    </sql:update>
</sql:transaction>

<sql:transaction> tag ensures that all database operations are processed successfully (committed) or all fail gracefully (rolled back) if an error occurs in any of the operations.

7. JSTL Functions

JSTL methods are utilities for data manipulation within JSP. While some functions take different data types, most of them are dedicated for String manipulation.

To enable JSTL methods in JSP, we’d add the taglib to our page:

<%@ taglib prefix = "fn"
  uri = "http://java.sun.com/jsp/jstl/functions" %>

Let’s look at these functions and how to use them.

7.1. fn:contains() and fn:containsIgnoreCase()

The fn:contains() method evaluates a String to check if it contains a given substring like this:

<c:set var = "string1" value = "This is first string"/>
<c:if test = "${fn:contains(string1, 'first')}">
    <p>Found 'first' in string<p>
</c:if>

The fn:contains() function takes two String arguments; the first is the source String and the second argument is the substring. It returns a boolean depending on the result of the evaluation.

The fn:containsIgnoreCase() function is a case-insensitive variant of the fn:contains() method and can be used like this:

<c:if test = "${fn:containsIgnoreCase(string1, 'first')}">
    <p>Found 'first' string<p>
</c:if>
<c:if test = "${fn:containsIgnoreCase(string1, 'FIRST')}">
    <p>Found 'FIRST' string<p>
</c:if>

7.3. The fn:endsWith() Function

The fn:endsWith() function evaluates a String to check if its suffix matches another substring. It takes two arguments; the first argument is the String whose suffix is to be tested while the second argument is the tested suffix.

We can define this like:

<c:if test = "${fn:endsWith(string1, 'string')}">
    <p>String ends with 'string'<p>
</c:if>

7.4. The fn:escapeXml() Function

The fn:escapeXML() function is used to escape XML markup in the input String like this:

<p>${fn:escapeXml(string1)}</p>

7.5. The fn:indexOf() Function

The fn:indexOf() function looks through a String and returns the index of the first occurrence of a given substring.

It takes two arguments; the first is the source String and the second argument is the substring to match and return the first occurrence.

fn:indexOf() function returns an integer and can be used like:

<p>Index: ${fn:indexOf(string1, "first")}</p>

7.6. The fn:join() Function

The fn:join() function concatenates all elements of an array into a single String and can be used like this:

<c:set var = "string3" value = "${fn:split(string1, ' ')}" />
<c:set var = "string4" value = "${fn:join(string3, '-')}" />

7.7. The fn:length() Function

The fn:length() function returns the number of elements in the given collection or the number of characters in the given String.

The fn:length() function takes a single Object which can either be a collection or a String and returns an integer like this:

<p>Length: ${fn:length(string1)}</p>

7.8. The fn:replace() Function

The fn:replace() function replaces all occurrences of a substring in a String with another String.

It takes three arguments; the source String, the substring to lookup in the source and the String to replace all occurrences of the substring just like this:

<c:set var = "string3" value = "${fn:replace(string1, 'first', 'third')}" />

7.9. The fn:split() Function

The fn:split() function performs split operation on a String using the specified delimiter. Here is an example usage:

<c:set var = "string3" value = "${fn:split(string1, ' ')}" />

7.10. The fn:startsWith() Function

The fn:startsWith() function checks the prefix of a String and returns true if it matches a given substring like this:

<c:if test = "${fn:startsWith(string1, 'This')}">
    <p>String starts with 'This'</p>
</c:if>

7.11. The fn:substring() Function

The fn:substring() function creates a substring from a source String at the starting and ending indices specified. We’d use it like this:

<c:set var = "string3" value = "${fn:substring(string1, 5, 15)}" />

7.12. The fn:substringAfter() Function

The fn:substringAfter() function checks a source String for a given substring and returns the String immediately after the first occurrence of the specified substring.

We’d use it like this:

<c:set var = "string3" value = "${fn:substringAfter(string1, 'is')}" />

7.13. The fn:substringBefore() Function

The fn:substringBefore() function checks a source String for a given substring and returns the String just before the first occurrence of the specified substring.

In our JSP page, it’ll look like this:

<c:set var = "string3" value = "${fn:substringBefore(string1, 'is')}" />

7.14. The fn:toLowerCase() Function

The fn:to LowerCase() function transforms all characters in a String to lowercase and can be used like this:

<c:set var = "string3" value = "${fn:toLowerCase(string1)}" />

7.15. The fn:toUpperCase() Function

The fn:toUpperCase() function transforms all characters in a String to uppercase:

<c:set var = "string3" value = "${fn:toUpperCase(string1)}" />

7.16. The fn:trim() Function

The fn:trim() function removes preceding and trailing whitespaces in a String:

<c:set var = "string1" value = "This is first String    "/>

9. Conclusion

In this extensive article, we’ve looked at the various JSTL tags and how to use them.

As usual, code snippets can be found over on GitHub.

Java Weekly, Issue 224

$
0
0

Here we go…

1. Spring and Java

>> Monitor and troubleshoot Java applications and services with Datadog 

Optimize performance with end-to-end tracing and out-of-the-box support for popular Java frameworks, application servers, and databases. Try it free.

>> ShuffleCollector [javaspecialists.eu]

We can easily sort a Stream, but shuffling has always been a bit tricky 🙂

>> Clearer Code with JDK 10 Local Variable Type Inference [marxsoftware.blogspot.com]

“var”s can make code more concise but also unreadable – just use it with care.

>> Spring IO Platform end-of-life announcement [spring.io]

Due to the insane popularity of Spring Boot, this isn’t surprising.

Also worth reading:

Webinars and presentations:

Time to upgrade:

2. Technical and Musings

>> User Authentication Best Practices Checklist [techblog.bozho.net]

This is a good bulleted list to have printed somewhere when you’re implementing authentication 🙂

>> Search on a static website [blog.frankel.ch]

Using static websites simplifies a number of things… but a simple search button is not one of these.

>> The Stack Overflow Age [joelonsoftware.com]

Great ideas are still out there, waiting to be implemented.

Also worth reading:

4. Comics

And my favorite Dilberts of the week:

>> The Cover Up [dilbert.com]

>> Blame the Mimes [dilbert.com]

>> Patents [dilbert.com]

5. Pick of the Week

>> HTTPS explained with carrier pigeons [freecodecamp.org]

Finding Min/Max in an Array

$
0
0

1. Introduction

In this short tutorial, we’re going to see how to find the maximum and the minimum values in an array, using Java 8’s Stream API.

We’ll start by finding the minimum in an array of integers, and then we’ll find the maximum in an array of objects.

2. Overview

There are many ways of finding the min or max value in an unordered array, and they all look something like:

SET MAX to array[0]
FOR i = 1 to array length - 1
  IF array[i] > MAX THEN
    SET MAX to array[i]
  ENDIF
ENDFOR

We’re going to look at how Java 8 can hide these details from us. But, in cases where Java’s API doesn’t suit us, we can always go back to this basic algorithm.

Because we need to check each value in the array, all implementations are O(n).

3. Finding the Smallest Value

The java.util.stream.IntStream interface provides the min method that will work just fine for our purposes.

As we are only working with integers, min doesn’t require a Comparator:

@Test
public void whenArrayIsOfIntegerThenMinUsesIntegerComparator() {
    int[] integers = new int[] { 20, 98, 12, 7, 35 };
    
    int min = Arrays.stream(integers)
      .min()
      .getAsInt();

    assertEquals(7, min);
}

Notice how we created the Integer stream object using the stream static method in Arrays. There are equivalent stream methods for each primitive array type.

Since the array could be empty, min returns an Optional, so to convert that to an int, we use getAsInt.

4. Finding the Largest Custom Object

Let’s create a simple POJO:

public class Car {
    private String model;
    private int topSpeed;

    // standard constructors, getters and setters
}

And then we can use the Stream API again to find the fastest car in an array of Cars:

@Test
public void whenArrayIsOfCustomTypeThenMaxUsesCustomComparator() {
    Car porsche = new Car("Porsche 959", 319);
    Car ferrari = new Car("Ferrari 288 GTO", 303);
    Car bugatti = new Car("Bugatti Veyron 16.4 Super Sport", 415);
    Car mcLaren = new Car("McLaren F1", 355);
    Car[] fastCars = { porsche, ferrari, bugatti, mcLaren };

    Car maxBySpeed = Arrays.stream(fastCars)
      .max(Comparator.comparing(Car::getTopSpeed))
      .orElseThrow(NoSuchElementException::new);

    assertEquals(bugatti, maxBySpeed);
}

In this case, the static method stream of Arrays returns an instance of the interface java.util.stream.Stream<T> where the method max requires a Comparator.

We could’ve constructed our own custom Comparator, but Comparator.comparing is much easier.

Note again that max returns an Optional instance for the same reason as before.

We can either get this value, or we can do whatever else is possible with Optionals, like orElseThrow that throws an exception if max doesn’t return a value.

5. Conclusion

We saw in this short article how easy and compact it is to find max and min on an array, using the Stream API of Java 8.

For more information on this library please refer to the Oracle documentation.

The implementation of all these examples and code snippets can be found over on GitHub.

Quick Guide to java.lang.System

$
0
0

1. Overview

In this tutorial, we’ll take a quick look at the java.lang.System class and its features and core functionality.

2. IO

System is a part of java.lang, and one of its main features is to give us access to the standard I/O streams.

Simply put, it exposes three fields, one for each stream:

  • out
  • err
  • in

2.1. System.out

System.out points to the standard output stream, exposing it as a PrintStream, and we can use it to print text to the console:

System.out.print("some inline message");

An advanced usage of System is to call System.setOut, which we can use to customize the location to which System.out will write:

// Redirect to a text file
System.setOut(new PrintStream("filename.txt"));

2.2. System.err

System.err is a lot like System.out. Both fields are instances of PrintStream, and both are for printing messages to the console.

But System.err represents standard error and we use that specifically to output error messages:

System.err.print("some inline error message");

Consoles will often render the error stream differently than the output stream.

For more information, check the PrintStream documentation.

2.3. System.in

System.in points to the standard in, exposing it as an InputStream, and we can use it for reading input from the console.

And while a bit more involved, we can still manage:

public String readUsername(int length) throws IOException {
    byte[] name = new byte[length];
    System.in.read(name, 0, length); // by default, from the console
    return new String(name);
}

By calling System.in.read, the application stops and waits for input from the standard in. Whatever the next length bytes are will be read from the stream and stored in the byte array.

Anything else typed by the user stays in the stream, waiting for another call to read.

Of course, operating at that low of a level can be challenging and error-prone, so we can clean it up a bit with BufferedReader:

public String readUsername() throws IOException {
    BufferedReader reader = new BufferedReader(
      new InputStreamReader(System.in));
    return reader.readLine();
}

With the above arrangement, readLine will read from System.in until the user hits return, which is a bit closer to what we might expect.

Note that we purposely don’t close the stream in this case. Closing the standard in means that it cannot be read again for the lifecycle of the program!

And finally, an advanced usage of System.in is to call System.setIn to redirect it to a different InputStream.

3. Utility Methods

System provides us with numerous methods to help us with things like:

  • Accessing the console
  • Copying arrays
  • Observing date and time
  • Exiting the JRE
  • Accessing runtime properties
  • Accessing environment variables, and
  • Administering garbage collection

3.1. Accessing the Console

Java 1.6 introduced another way of interacting with the console than simply using System.out and in directly.

We can access it by calling System.console:

public String readUsername() {
    Console console = System.console();	 	 
	 	 
    return console == null ? null :	 
      console.readLine("%s", "Enter your name: ");	 	 
}

Note that depending upon the underlying operating system and how we launch Java to run the current program, console might return null, so always make sure to check before using.

Check out the Console documentation for more uses.

3.2. Copying Arrays

System.arraycopy is an old C-style way of copying one array into another.

Mostly, arraycopy is intended to copy one complete array into another array:

int[] a = {34, 22, 44, 2, 55, 3};
int[] b = new int[a.length];

System.arraycopy(a, 0, b, 0, a.length);
assertArrayEquals(a, b);

However, we can specify the starting position for both arrays, as well as how many elements to copy.

For example, let’s say we want to copy 2 elements from a, starting at a[1] to b, starting at b[3]:

System.arraycopy(a, 1, b, 3, 2); 
assertArrayEquals(new int[] {0, 0, 0, 22, 44, 0}, b);

Also, remember that arraycopy will throw:

  • NullPointerException if either array is null
  • IndexOutOfBoundsException if the copy references either array beyond its range
  • ArrayStoreException if the copy results in a type mismatch

3.3. Observing Date and Time

There’re two methods related to time in System. One is currentTimeMillis and the other is nanoTime.

currentTimeMillis returns the number of milliseconds passed since the Unix Epoch, which is January 1, 1970 12:00 AM UTC:

public long nowPlusOneHour() {
    return System.currentTimeMillis() + 3600 * 1000L;
}

public String nowPrettyPrinted() {
    return new Date(System.currentTimeMillis()).toString();
}

nanoTime returns the time relative to JVM startup. We can call it multiple times to mark the passage of time in the application:

long startTime = System.nanoTime();
// ...
long endTime = System.nanoTime();

assertTrue(endTime - startTime < 10000);

Note that since nanoTime is so fine-grained, it’s safer to do endTime – startTime < 10000 than endTime < startTime due to the possibility of numerical overflow.

3.4. Exiting the Program

If we want to programmatically exit the currently executed program, System.exit will do the trick.

To invoke exit, we need to specify an exit code, which will get sent to the console or shell that launched the program.

By convention in Unix, a status of 0 means a normal exit, while non-zero means some error occurred:

if (error) {
    System.exit(1);
} else {
    System.exit(0);
}

Note that for most programs nowadays, it’d be strange to need to call this. When called in a web server application, for example, it may take down the entire site!

3.5. Accessing Runtime Properties

System provides access to runtime properties with getProperty.

And we can manage them with setProperty and clearProperty:

public String getJavaVMVendor() {
    System.getProperty("java.vm.vendor");
}
    
System.setProperty("abckey", "abcvaluefoo");
assertEquals("abcvaluefoo", System.getProperty("abckey"));

System.clearProperty("abckey");
assertNull(System.getProperty("abckey"));

Properties specified via -D are accessible via getProperty.

We can also provide a default:

System.clearProperty("dbHost");
String myKey = System.getProperty("dbHost", "db.host.com");
assertEquals("db.host.com", myKey);

And System.getProperties provides a collection of all system properties:

Properties properties = System.getProperties();

From which we can do any Properties operations:

public void clearAllProperties() {
    System.getProperties().clear();
}

3.6. Accessing Environment Variables

System also provides read-only access to environment variables with getenv.

If we want to access the PATH environment variable, for example, we can do:

public String getPath() {
    return System.getenv("PATH");
}

3.7. Administering Garbage Collection

Typically, garbage collection efforts are opaque to our programs. On occasion, though, we may want to make a direct suggestion to the JVM.

System.runFinalization is a method that allows us to suggest that the JVM run its finalize routine.

System.gc is a method that allows us to suggest that the JVM run its garbage collection routine.

Since contracts of these two methods don’t guarantee that finalization or garbage collection will run, their usefulness is narrow.

However, they could be exercised as an optimization, say invoking gc when a desktop app gets minimized:

public void windowStateChanged(WindowEvent event) {
    if ( event == WindowEvent.WINDOW_DEACTIVATED ) {
        System.gc(); // if it ends up running, great!
    }
}

For more on finalization, check out our finalize guide.

4. Conclusion

In this article, we got to see some of the fields and methods System provides. The complete list can be found in the official System documentation.

Also, check out all the examples in this article over on Github.

Assert an Exception is Thrown in JUnit 4 and 5

$
0
0

1. Introduction

In this quick tutorial, we’ll be looking at how to test if an exception was thrown, using JUnit library.

Of course, we’ll make sure to cover both the JUnit 4 and JUnit 5 versions.

2. JUnit 5

JUnit 5 Jupiter assertions API introduces the assertThrows method for asserting exceptions.

This takes the type of the expected exception, and an Executable functional interface where we can pass the code under test through a lambda expression:

@Test
public void whenExceptionThrown_thenAssertionSucceeds() {
    String test = null;
    assertThrows(NullPointerException.class, () -> {
        test.length();
    });
}

It’s important to note here that this assertion is satisfied when the enclosed code throws an exception of type NullPointerException or any of its derived types.

This means if we pass Exception as the expected exception type, any exception thrown will make the assertion succeed since Exception is the supertype for all exceptions.

If we change the test above to expect a RuntimeException, this will also pass:

@Test
public void whenDerivedExceptionThrown_thenAssertionSucceds() {
    String test = null;
    assertThrows(RuntimeException.class, () -> {
        test.length();
    });
}

The assertThrows() method enables more fine-grained control for exception assertion logic because we can use it around specific parts of the code.

3. JUnit 4

When using JUnit 4, we can simply use the expected attribute of the @Test annotation to declare we expect an exception to be thrown anywhere in the annotated test method.

As a result, the test will fail if the specified exception isn’t thrown when the test is run and will pass if it’s thrown:

@Test(expected = NullPointerException.class)
public void whenExceptionThrown_thenExpectationSatisfied() {
    String test = null;
    test.length();
}

In this example, we’ve declared that we’re expecting our test code to result in a NullPointerException.

This is enough if we’re only interested in asserting that an exception is thrown.

When we need to verify some other properties of the exception, we can use the ExpectedException rule.

Let’s see an example of verifying the message property of an exception:

@Rule
public ExpectedException exceptionRule = ExpectedException.none();

@Test
public void whenExceptionThrown_thenRuleIsApplied() {
    exceptionRule.expect(NumberFormatException.class);
    exceptionRule.expectMessage("For input string");
    Integer.parseInt("1a");
}

In the example above, we’re first declaring the ExpectedException rule. Then, in our test, we’re asserting that the code that attempts to parse an Integer value will result in a NumberFormatException with the message “For input string”.

4. Conclusion

In this article, we focused on and covered asserting exceptions with both JUnit 4 and JUnit 5.

The full source code for the examples is available over on GitHub.

@Lookup Annotation in Spring

$
0
0

1. Introduction

In this quick tutorial, we’ll take a look at Spring’s method-level dependency injection support, via the @Lookup annotation.

2. Why @Lookup?

A method annotated with @Lookup tells Spring to return an instance of the method’s return type when we invoke it.

Essentially, Spring will override our annotated method and use our method’s return type and parameters as arguments to BeanFactory#getBean.

@Lookup is useful for:

  • Injecting a prototype-scoped bean into a singleton bean (similar to Provider)
  • Injecting dependencies procedurally

Note also that @Lookup is the Java equivalent of the XML element lookup-method.

3. Using @Lookup

3.1. Injecting prototype-scoped bean into a singleton bean

If we happen to decide to have a prototype Spring bean, then we are almost immediately faced with the problem of how will our singleton Spring beans access these prototype Spring beans?

Now, Provider is certainly one way, though @Lookup is more versatile in some respects.

First, let’s create a prototype bean that we will later inject into a singleton bean:

@Component
@Scope("prototype")
public class SchoolNotification {
    // ... prototype-scoped state
}

And if we create a singleton bean that uses @Lookup:

@Component
public class StudentServices {

    // ... member variables, etc.

    @Lookup
    public SchoolNotification getNotification() {
        return null;
    }

    // ... getters and setters
}

Using @Lookup, we can get an instance of SchoolNotification through our singleton bean:

@Test
public void whenLookupMethodCalled_thenNewInstanceReturned() {
    // ... initialize context
    StudentServices first = this.context.getBean(StudentServices.class);
    StudentServices second = this.context.getBean(StudentServices.class);
       
    assertEquals(first, second); 
    assertNotEquals(first.getNotification(), second.getNotification()); 
}

Note that in StudentServices, we left the getNotification method as a stub.

This is because Spring overrides the method with a call to beanFactory.getBean(StudentNotification.class), so we can leave it empty.

3.2. Injecting Dependencies Procedurally

Still more powerful, though, is that @Lookup allows us to inject a dependency procedurally, something that we cannot do with Provider.

Let’s enhance StudentNotification with some state:

@Component
@Scope("prototype")
public class SchoolNotification {
    @Autowired Grader grader;

    private String name;
    private Collection<Integer> marks;

    public SchoolNotification(String name) {
        // ... set fields
    }

    // ... getters and setters

    public String addMark(Integer mark) {
        this.marks.add(mark);
        return this.grader.grade(this.marks);
    }
}

Now, it is dependent on some Spring context and also additional context that we will provide procedurally.

We can then add a method to StudentServices that takes student data and persists it:

public abstract class StudentServices {
 
    private Map<String, SchoolNotification> notes = new HashMap<>();
 
    @Lookup
    protected abstract SchoolNotification getNotification(String name);

    public String appendMark(String name, Integer mark) {
        SchoolNotification notification
          = notes.computeIfAbsent(name, exists -> getNotification(name)));
        return notification.addMark(mark);
    }
}

At runtime, Spring will implement the method in the same way, with a couple of additional tricks.

First, note that it can call a complex constructor as well as inject other Spring beans, allowing us to treat SchoolNotification a bit more like a Spring-aware method.

It does this by implementing getSchoolNotification with a call to beanFactory.getBean(SchoolNotification.class, name).

Second, we can sometimes make the @Lookup-annotated method abstract, like the above example.

Using abstract is a bit nicer-looking than a stub, but we can only use it when we don’t component-scan or @Bean-manage the surrounding bean:

@Test
public void whenAbstractGetterMethodInjects_thenNewInstanceReturned() {
    // ... initialize context

    StudentServices services = context.getBean(StudentServices.class);    
    assertEquals("PASS", services.appendMark("Alex", 89));
    assertEquals("FAIL", services.appendMark("Bethany", 78));
    assertEquals("PASS", services.appendMark("Claire", 96));
}

With this setup, we can add Spring dependencies as well as method dependencies to SchoolNotification.

4. Limitations

Despite @Lookup‘s versatility, there are a few notable limitations:

  • @Lookup-annotated methods, like getNotification, must be concrete when the surrounding class, like Student, is component-scanned. This is because component scanning skips abstract beans.
  • @Lookup-annotated methods won’t work at all when the surrounding class is @Bean-managed.

In those circumstances, if we need to inject a prototype bean into a singleton, we can look to Provider as an alternative.

5. Conclusion

In this quick article, we learned how and when to use Spring’s @Lookup annotation, including how to use it to inject prototype-scoped beans into singleton beans and how to use it to inject dependencies procedurally.

All the code used for this tutorial can be found over on Github.

Spring Boot: Customize Whitelabel Error Page

$
0
0

1. Overview

In this article, we’re going to look at how to disable and customize the default error page for a Spring Boot application as proper error handling depicts professionalism and quality work.

2. Disabling the Whitelabel Error Page

First, let’s see how we can disable the white label error page entirely, by setting the server.error.whitelabel.enabled property to false:

server.error.whitelabel.enabled=false

Adding this entry to the application.properties file will disable the error page and show a concise page that originates from the underlying application container, e.g., Tomcat.

We can achieve the same result by excluding the ErrorMvcAutoConfiguration bean. We can do this by either adding this entry to the properties file:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration

#for Spring Boot 2.0
#spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration

Or by adding this annotation to the main class:

@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})

All the methods mentioned above will disable the white label error page. That leaves us with the question of who then actually handles the error?

Well, as mentioned above, it’s usually the underlying application container. The good thing is we can further customize things by showing our custom error pages instead of all the defaults – this is the focus of the next section.

3. Displaying Custom Error Pages

We first need to create a custom HTML error page.

We’ll save the file as error.html since we’re using Thymeleaf template engine:

<!DOCTYPE html>
<html>
<body>
<h1>Something went wrong! </h1>
<h2>Our Engineers are on it</h2>
<a href="/">Go Home</a>
</body>
</html>

If we save this file in resources/templates directory, it’ll automatically be picked up by the default Spring Boot’s BasicErrorController.

This is all we need to display our custom error page. With some styling, we’ll now have a much nicer looking error page for our users:

 

Spring Boot Custom Error Page

We can be more specific by naming the file with the HTTP status code we want it used e.g. saving the file as 404.html in resources/templates/error means it’ll be used explicitly for 404 errors.

3.1. A Custom ErrorController

The limitation so far is that we can’t run custom logic when errors occur. To achieve that, we have to create an error controller bean that’ll replace the default one.

For this, we have to create a class that implements the ErrorController interface and overrides its getErrorPath() to return a custom path to call when an error occurred:

@Controller
public class MyErrorController implements ErrorController  {

    @RequestMapping("/error")
    public String handleError() {
        //do something like logging
        return "error";
    }

    @Override
    public String getErrorPath() {
        return "/error";
    }
}

In the snippet above, we also annotate the class with @Controller and create a mapping for the path that is returned by the getErrorPath(). This way the controller can handle calls to the /error path.

In the handleError(), we return the custom error page we created earlier. If we trigger a 404 error now, it’s our custom page that will be displayed.

Let’s further enhance the handleError() to display specific error pages for different error types.

For example, we can have nicely designed pages specifically for 404 and 500 error types. Then we can use the HTTP status code of the error to determine a suitable error page to display:

@RequestMapping("/error")
public String handleError(HttpServletRequest request) {
    Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
    
    if (status != null) {
        Integer statusCode = Integer.valueOf(status.toString());
    
        if(statusCode == HttpStatus.NOT_FOUND.value()) {
            return "error-404";
        }
        else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
            return "error-500";
        }
    }
    return "error";
}

Then, for a 404 error, for example, we’ll see the error-404.html page:

4. Conclusion

With this information, we can go now handle errors more elegantly and show our users an aesthetic page.

As always, the complete source code is available over on Github.


Internationalization and Localization in Java 8

$
0
0

1. Overview

Internationalization is a process of preparing an application to support various linguistic, regional, cultural or political-specific data. It is an essential aspect of any modern multi-language application.

For further reading, we should know that there’s a very popular abbreviation (probably more popular than the actual name) for internationalization – i18n due to the 18 letters between ‘i’ and ‘n’.

It’s crucial for present-day enterprise programs to serve people from different parts of the world or multiple cultural areas. Distinct cultural or language regions don’t only determine language-specific descriptions but also currency, number representation and even divergent date and time composition.

For instance, let’s focus on country-specific numbers. They have various decimal and thousand separators:

  • 102,300.45 (United States)
  • 102 300,45 (Poland)
  • 102.300,45 (Germany)

There are different date formats as well:

  • Monday, January 1, 2018 3:20:34 PM CET (United States)
  • lundi 1 janvier 2018 15 h 20 CET (France).
  • 2018年1月1日 星期一 下午03时20分34秒 CET (China)

What’s more, different countries have unique currency symbols:

  • £1,200.60 (United Kingdom)
  • € 1.200,60 (Italy)
  • 1 200,60 € (France)
  • $1,200.60 (United States)

An important fact to know is that even if countries have the same currency and currency symbol – like France and Italy – the position of their currency symbol could be different.

2. Localization

Within Java, we have a fantastic feature at our disposal called the Locale class.

It allows us to quickly differentiate between cultural locales and format our content appropriately. It’s essential for within the internationalization process. The same as i18n, Localization also has its abbreviation – l10n.

The main reason for using Locale is that all required locale-specific formatting can be accessed without recompilation. An application can handle multiple locales at the same time so supporting new language is straightforward.

Locales are usually represented by language, country, and variant abbreviation separated by an underscore:

  • de (German)
  • it_CH (Italian, Switzerland)
  • en_US_UNIX (United State, UNIX platform)

2.1. Fields

We have already learned that Locale consists of language code, country code, and variant. There are two more possible fields to set: script and extensions.

Let’s have a look through a list of fields and see what the rules are:

  • Language can be an ISO 639 alpha-2 or alpha-3 code or registered language subtag.
  • Region (Country) is ISO 3166 alpha-2 country code or UN numeric-3 area code.
  • Variant is a case-sensitive value or set of values specifying a variation of a Locale.
  • Script must be a valid ISO 15924 alpha-4 code.
  • Extensions is a map which consists of single character keys and String values.

The IANA Language Subtag Registry contains possible values for language, region, variant and script.

There is no list of possible extension values, but the values must be well-formed BCP-47 subtags. The keys and values are always converted to lower case.

2.2. Locale.Builder

There are several ways of creating Locale objects. One possible way utilizes Locale.Builder. Locale.Builder has five setter methods which we can use to build the object and at the same time validate those values:

Locale locale = new Locale.Builder()
  .setLanguage("fr")
  .setRegion("CA")
  .setVariant("POSIX")
  .setScript("Latn")
  .build();

The String representation of the above Locale is fr_CA_POSIX_#Latn.

It’s good to know that setting ‘variant’ may be a little bit tricky as there’s no official restriction on variant values, although the setter method requires it to be BCP-47 compliant.

Otherwise, it will throw IllformedLocaleException.

In the case where we need to use value that doesn’t pass validation, we can use Locale constructors as they don’t validate values.

2.3. Constructors

Locale has three constructors:

  • new Locale(String language)
  • new Locale(String language, String country)
  • new Locale(String language, String country, String variant)

A 3-parameter constructor:

Locale locale = new Locale("pl", "PL", "UNIX");

A valid variant must be a String of 5 to 8 alphanumerics or single numeric followed by 3 alphanumerics. We can only apply “UNIX” to the variant field only via constructor as it doesn’t meet those requirements.

However, there’s one drawback of using constructors to create Locale objects – we can’t set extensions and script fields.

2.4. Constants

This is probably the simplest and the most limited way of getting Locales. The Locale class has several static constants which represent the most popular country or language:

Locale japan = Locale.JAPAN;
Locale japanese = Locale.JAPANESE;

2.5. Language Tags

Another way of creating Locale is calling the static factory method forLanguageTag(String languageTag). This method requires a String that meets the IETF BCP 47 standard.

This is how we can create the UK Locale:

Locale uk = Locale.forLanguageTag("en-UK");

2.6. Available Locales

Even though we can create multiple combinations of Locale objects, we may not be able to use them.

An important note to be aware of is that the Locales on a platform are dependent on those that have been installed within the Java Runtime.

As we use Locales for formatting, the different formatters may have an even smaller set of Locales available that are installed in the Runtime.

Let’s check how to retrieve arrays of available locales:

Locale[] numberFormatLocales = NumberFormat.getAvailableLocales();
Locale[] dateFormatLocales = DateFormat.getAvailableLocales();
Locale[] locales = Locale.getAvailableLocales();

After that, we can check whether our Locale resides among available Locales.

We should remember that the set of available locales is different for various implementations of the Java Platform and various areas of functionality.

The complete list of supported locales is available on the Oracle’s Java SE Development Kit webpage.

2.7. Default Locale

While working with localization, we might need to know what the default Locale on our JVM instance is. Fortunately, there’s a simple way to do that:

Locale defaultLocale = Locale.getDefault();

Also, we can specify a default Locale by calling a similar setter method:

Locale.setDefault(Locale.CANADA_FRENCH);

It’s especially relevant when we’d like to create JUnit tests that don’t depend on a JVM instance.

3. Numbers and Currencies

This section refers to numbers and currencies formatters that should conform to different locale-specific conventions.

To format primitive number types (int, double) as well as their object equivalents (Integer, Double), we should use NumberFormat class and its static factory methods.

Two methods are interesting for us:

  • NumberFormat.getInstance(Locale locale)
  • NumberFormat.getCurrencyInstance(Locale locale)

Let’s examine a sample code:

Locale usLocale = Locale.US;
double number = 102300.456d;
NumberFormat usNumberFormat = NumberFormat.getInstance(usLocale);

assertEquals(usNumberFormat.format(number), "102,300.456");

As we can see it’s as simple as creating Locale and using it to retrieve NumberFormat instance and formatting a sample number. We can notice that the output includes locale-specific decimal and thousand separators.

Here’s another example:

Locale usLocale = Locale.US;
BigDecimal number = new BigDecimal(102_300.456d);

NumberFormat usNumberFormat = NumberFormat.getCurrencyInstance(usLocale); 
assertEquals(usNumberFormat.format(number), "$102,300.46");

Formatting a currency involves the same steps as formatting a number. The only difference is that the formatter appends currency symbol and round decimal part to two digits.

4. Date and Time

Now, we’re going to learn about dates and times formatting which’s probably more complex than formatting numbers.

First of all, we should know that date and time formatting significantly changed in Java 8 as it contains completely new Date/Time API. Therefore, we’re going to look through different formatter classes.

4.1. DateTimeFormatter

Since Java 8 was introduced, the main class for localizing of dates and times is the DateTimeFormatter class. It operates on classes that implement TemporalAccessor interface, for example, LocalDateTime, LocalDate, LocalTime or ZonedDateTime. To create a DateTimeFormatter we must provide at least a pattern, and then Locale. Let’s see an example code:

Locale.setDefault(Locale.US);
LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
String pattern = "dd-MMMM-yyyy HH:mm:ss.SSS";

DateTimeFormatter defaultTimeFormatter = DateTimeFormatter.ofPattern(pattern);
DateTimeFormatter deTimeFormatter = DateTimeFormatter.ofPattern(pattern, Locale.GERMANY);

assertEquals(
  "01-January-2018 10:15:50.000", 
  defaultTimeFormatter.format(localDateTime));
assertEquals(
  "01-Januar-2018 10:15:50.000", 
  deTimeFormatter.format(localDateTime));

We can see that after retrieving DateTimeFormatter all we have to do is to call the format() method.

For a better understanding, we should familiarize with possible pattern letters.

Let’s look at letters for example:

Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   y       year-of-era                 year              2004; 04
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

   H       hour-of-day (0-23)          number            0
   m       minute-of-hour              number            30
   s       second-of-minute            number            55
   S       fraction-of-second          fraction          978

All possible pattern letters with explanation can be found in the Java documentation of DateTimeFormatter. It’s worth to know that final value depends on the number of symbols. There is ‘MMMM’ in the example which prints the full month name whereas a single ‘M’ letter would give the month number without a leading 0.

To finish on DateTimeFormatter, let’s see how we can format LocalizedDateTime:

LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
ZoneId losAngelesTimeZone = TimeZone.getTimeZone("America/Los_Angeles").toZoneId();

DateTimeFormatter localizedTimeFormatter = DateTimeFormatter
  .ofLocalizedDateTime(FormatStyle.FULL);
String formattedLocalizedTime = localizedTimeFormatter.format(
  ZonedDateTime.of(localDateTime, losAngelesTimeZone));

assertEquals("Monday, January 1, 2018 10:15:50 AM PST", formattedLocalizedTime);

In order to format LocalizedDateTime, we can use the ofLocalizedDateTime(FormatStyle dateTimeStyle) method and provide a predefined FormatStyle.

For a more in-depth look at Java 8 Date/Time API, we have an existing article here.

4.2. DateFormat and SimpleDateFormatter

As it’s still common to work on projects that make use of Dates and Calendars, we’ll briefly introduce capabilities of formatting dates and times with DateFormat and SimpleDateFormat classes.

Let’s analyze abilities of the first one:

GregorianCalendar gregorianCalendar = new GregorianCalendar(2018, 1, 1, 10, 15, 20);
Date date = gregorianCalendar.getTime();

DateFormat ffInstance = DateFormat.getDateTimeInstance(
  DateFormat.FULL, DateFormat.FULL, Locale.ITALY);
DateFormat smInstance = DateFormat.getDateTimeInstance(
  DateFormat.SHORT, DateFormat.MEDIUM, Locale.ITALY);

assertEquals("giovedì 1 febbraio 2018 10.15.20 CET", ffInstance.format(date));
assertEquals("01/02/18 10.15.20", smInstance.format(date));

DateFormat works with Dates and has three useful methods:

  • getDateTimeInstance
  • getDateInstance
  • getTimeInstance

All of them take predefined values of DateFormat as a parameter. Each method is overloaded, so passing Locale is possible as well. If we want to use a custom pattern, as it’s done in DateTimeFormatter, we can use SimpleDateFormat. Let’s see a short code snippet:

GregorianCalendar gregorianCalendar = new GregorianCalendar(
  2018, 1, 1, 10, 15, 20);
Date date = gregorianCalendar.getTime();
Locale.setDefault(new Locale("pl", "PL"));

SimpleDateFormat fullMonthDateFormat = new SimpleDateFormat(
  "dd-MMMM-yyyy HH:mm:ss:SSS");
SimpleDateFormat shortMonthsimpleDateFormat = new SimpleDateFormat(
  "dd-MM-yyyy HH:mm:ss:SSS");

assertEquals(
  "01-lutego-2018 10:15:20:000", fullMonthDateFormat.format(date));
assertEquals(
  "01-02-2018 10:15:20:000" , shortMonthsimpleDateFormat.format(date));

5. Customization

Due to some good design decisions, we’re not tied to a locale-specific formatting pattern, and we can configure almost every detail to be fully satisfied with an output.

To customize number formatting, we can use DecimalFormat and DecimalFormatSymbols.

Let’s consider a short example:

Locale.setDefault(Locale.FRANCE);
BigDecimal number = new BigDecimal(102_300.456d);

DecimalFormat zeroDecimalFormat = new DecimalFormat("000000000.0000");
DecimalFormat dollarDecimalFormat = new DecimalFormat("$###,###.##");

assertEquals(zeroDecimalFormat.format(number), "000102300,4560");
assertEquals(dollarDecimalFormat.format(number), "$102 300,46");

The DecimalFormat documentation shows all possible pattern characters. All we need to know now is that “000000000.000” determines leading or trailing zeros, ‘,’ is a thousand separator, and ‘.’ is decimal one.

It’s also possible to add a currency symbol. We can see below that the same result can be achieved by using DateFormatSymbol class:

Locale.setDefault(Locale.FRANCE);
BigDecimal number = new BigDecimal(102_300.456d);

DecimalFormatSymbols decimalFormatSymbols = DecimalFormatSymbols.getInstance();
decimalFormatSymbols.setGroupingSeparator('^');
decimalFormatSymbols.setDecimalSeparator('@');
DecimalFormat separatorsDecimalFormat = new DecimalFormat("$###,###.##");
separatorsDecimalFormat.setGroupingSize(4);
separatorsDecimalFormat.setCurrency(Currency.getInstance(Locale.JAPAN));
separatorsDecimalFormat.setDecimalFormatSymbols(decimalFormatSymbols);

assertEquals(separatorsDecimalFormat.format(number), "$10^2300@46");

As we can see, DecimalFormatSymbols class enables us to specify any number formatting we can imagine.

To customize SimpleDataFormat, we can use DateFormatSymbols.

Let’s see how simple is a change of day names:

Date date = new GregorianCalendar(2018, 1, 1, 10, 15, 20).getTime();
Locale.setDefault(new Locale("pl", "PL"));

DateFormatSymbols dateFormatSymbols = new DateFormatSymbols();
dateFormatSymbols.setWeekdays(new String[]{"A", "B", "C", "D", "E", "F", "G", "H"});
SimpleDateFormat newDaysDateFormat = new SimpleDateFormat(
  "EEEE-MMMM-yyyy HH:mm:ss:SSS", dateFormatSymbols);

assertEquals("F-lutego-2018 10:15:20:000", newDaysDateFormat.format(date));

6. Resource Bundles

Finally, the crucial part of internationalization in the JVM is the Resource Bundle mechanism.

The purpose of a ResourceBundle is to provide an application with localized messages/descriptions which can be externalized to the separate files. We cover usage and configuration of the Resource Bundle in one of our previous articles – guide to the Resource Bundle.

7. Conclusion

Locales and the formatters that utilize them are tools that help us create an internationalized application. These tools allow us to create an application which can dynamically adapt to the user’s linguistic or cultural settings without multiple builds or even needing to worry about whether Java supports the Locale.

In a world where a user can be anywhere and speak any language, the ability to apply these changes means our applications can be more intuitive and understandable by more users globally.

When working with Spring Boot applications, we also have a convenient article for Spring Boot Internationalization.

The source code of this tutorial, with full examples, can be found over on GitHub.

A Quick Guide to the JVM Languages

$
0
0

1. Introduction

Besides Java, other languages can run on the Java Virtual Machine like Scala, Kotlin, Groovy, Clojure.

In the following sections, we’ll take a high-level look at the most popular JVM languages.

Of course, we’ll start with the forerunner of JVM languages – Java.

2. Java

2.1. Overview

Java is a general-purpose programming language embracing the Object-Oriented Paradigm.

A core feature of the language is the cross-platform portability, which means that programs written on one platform are executable on any combination of software and hardware with adequate runtime support. This is achieved by compiling code into bytecode first, instead of directly to platform-specific machine code.

Java bytecode instructions are analogous to the machine code, but they’re interpreted by a Java Virtual Machine (JVM) specific to the host operating system and hardware combination.

Although originally an object-oriented language, Java has started adopting concepts from other programming paradigms like functional programming.

Let’s have a quick look at some of Java’s main features:

  • Object-oriented
  • Strongly statically typed
  • Platform-independent
  • Garbage-collected
  • Multithreaded

2.2. Examples

Let’s see how a simple “Hello, World!” example looks like:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

In this example, we’ve created a class named HelloWorld and defined the main method which prints a message on the console.

Next, we’ll use the javac command to generate the bytecode which can be executed on a JVM:

javac HelloWorld.java

Finally, the java command executes the generated bytecode on JVM:

java HelloWorld

For more Java examples, check out our list of tutorials.

3. Scala

3.1. Overview

Scala stands for “scalable language”. Scala’s a statically typed language which combines two important programming paradigms, namely object-oriented and functional programming. 

The language originated in 2004 but became more popular in recent years.

Scala is a pure Object-Oriented language as it doesn’t support primitives. Scala provides the ability to define classes, objects, methods along with functional programming features like traits, algebraic data types, or type classes.

A few important features of Scala are:

  • Functional, Object-oriented
  • Strongly statically typed
  • Algebraic Data Types
  • Pattern Matching
  • Enhanced Immutability Support
  • Lazy Computation
  • Multithreaded

3.2. Examples

First, let’s take a look at the same “Hello, World!” example as before, this time in Scala:

object HelloWorld {
    def main(args: Array[String]): Unit = println("Hello, world!")
}

In this example, we’ve created a singleton object named HelloWorld and the main method.

Next, to compile this, we can use scalac:

scalac HelloWorld.scala

The scala command executes the generated bytecode on JVM:

scala HelloWorld

4. Kotlin

4.1. Overview

Kotlin is a statically typed, general-purpose, open-source language developed by JetBrains team, which brings together the Object-oriented and functional paradigms.

The main focus while developing Kotlin was Java interoperability, safety (exception handling), conciseness and better tooling support.

Since the release of Android Studio 3.0, Kotlin is a fully supported programming language by Google on the Android Platform. It’s also included in the Android Studio IDE package as an alternative to the standard Java compiler.

Some important Kotlin features:

  • Object-oriented + Functional
  • Strongly statically typed
  • Concise
  • Interoperable with Java

Our introduction to Kotlin also contains more specifics on the features.

4.2. Examples

Let’s see the “Hello, World!” example in Kotlin:

fun main(args: Array<String>) println("Hello, World!")

We can write the code above in a new file called helloWorld.kt.

Then, we’ll use the kotlinc command to compile this and generates bytecode which can be executed on a JVM:

kotlinc helloWorld.kt -include-runtime -d helloWorld.jar

The -d option is used to indicate the output file for class files or a .jar file name. The -include-runtime option makes the resulting .jar file self-contained and runnable by including the Kotlin runtime library in it.

Then, the java command executes the generated bytecode on JVM:

java -jar helloWorld.jar

Let’s also see another example of printing a list of items using a for loop:

fun main(args: Array<String>) {
    val items = listOf(1, 2, 3, 4)
    for (i in items) println(i)
}

5. Groovy

5.1. Overview

Groovy is an object-oriented, optionally typed, dynamic domain specific language (DSL), with support for static-typing and static compilation capabilities. It’s aimed at improving developer productivity, with easy to learn syntax.

Groovy integrates easily with any Java program and immediately adds powerful features, like scripting capabilities, runtime and compile-time meta-programming and functional programming features.

Let’s highlight a few important features:

  • Object-oriented with functional features like Higher-order functions, currying, closures
  • Typing – Dynamic, Static, Strong, Duck
  • Domain Specific Language
  • Interoperability with Java
  • Productivity by conciseness
  • Operator overloading

5.2. Examples

First, let’s see our “Hello, World!” example in Groovy:

println("Hello world")

We wrote the above code in a new file called HelloWorld.groovy. Now we can run this code in two ways: by compiling then executing or by just running uncompiled code.

We can compile a .groovy file using the groovyc command as follows:

groovyc HelloWorld.groovy

Then, we’ll use the java command for executing the groovy code:

java -cp <GROOVY_HOME>\embeddable\groovy-all-<VERSION>.jar;. HelloWorld

For example, the command above could look like:

java -cp C:\utils\groovy-1.8.1\embeddable\groovy-all-1.8.1.jar;. HelloWorld

Let’s also see how we can use the groovy command to execute the .groovy file without compiling:

groovy HelloWorld.groovy

Finally, here’s another example of printing a list of items with the index:

list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list.eachWithIndex { it, i -> println "$i: $it"}

Have a look at more Groovy examples in our introduction article.

6. Clojure

6.1. Overview

Clojure is a general-purpose functional programming language. The language runs on JVM as well as Microsoft’s Common Language Runtime. Clojure is a compiled language still, it remains dynamic, as its features are supported at runtime.

The Clojure designers wanted to design modern Lisp which can run on JVM. That’s why it’s also known as a dialect of the Lisp programming language. Similar to Lisps, Clojure treats code as data and has a macro system as well.

Some important Clojure features:

  • Functional
  • Typing – Dynamic, Strong, recently started supporting gradual typing
  • Designed for concurrency
  • Runtime polymorphism

6.2. Examples

Unlike other JVM languages, it’s not that straightforward to create simple “Hello, World!” program in Clojure.

We’ll use the Leiningen tool for running our example.

First, we’ll create a simple project with default template using the following command:

lein new hello-world

The project will be created with following file structure:

./project.clj
./src
./src/hello-world
./src/hello-world/core.clj

Now we need to update the ./project.ctj file with the following content to set the main source file:

(defproject hello-world "0.1.0-SNAPSHOT"
  :main hello-world.core
  :dependencies [[org.clojure/clojure "1.5.1"]])

Now we’re set to update our code to print “Hello, World!” in the ./src/hello-world/core.clj file:

(ns hello-world.core)

(defn -main [& args]
    (println "Hello, World!"))

Finally, we’ll use the lein command to execute the code above, after moving to the project’s root directory:

cd hello-world
lein run

7. Other JVM Languages

7.1. Jython

Jython is the Java platform implementation of Python which runs on the JVM.

This language was initially designed to enabled writing high-performance application without sacrificing interactivity. Jython is object-oriented, multi-threaded and uses Java’s garbage collector for efficiently cleaning up the memory.

Jython includes most of the modules which are part of the Python language. It can also import and use any classes from the Java libraries.

Let’s see a quick “Hello, World!” example:

print "Hello, world!"

7.2. JRuby

JRuby is an implementation of the Ruby programming language to run on the Java Virtual Machine.

The JRuby language is high performance and multi-threaded, with a vast variety of available libraries from Java and Ruby. Also, it combines features from both languages like object-oriented programming and duck-typing.

Let’s print “Hello, World!” in JRuby:

require "java"

stringHello= "Hello World"
puts "#{stringHello.to_s}"

8. Conclusion

In this article, we’ve studied many popular JVM languages along with basic code examples. These languages implement various programming paradigms like object-oriented, functional, static typing, dynamic typing.

So far it shows that even with the JVM dating back to 1995, it still stands as a highly relevant and compelling platform for modern-day programming languages.

Java List UnsupportedOperationException

$
0
0

1. Overview

In this quick tutorial, we’ll discuss a common Exception that can occur when working with some the API of most List implementations – the UnsupportedOperationException.

A java.util.List has more functionality than an ordinary array can support. For instance, with only one built-in method call, it’s possible to check if a specific element is inside the structure. That’s typically why we sometimes need to convert an array to a List or Collection.

For an introduction to the core Java List implementation – the ArrayList – please refer to this article.

2. UnsupportedOperationException

A frequent way in which this error occurs is when we use asList() method from java.util.Arrays:

public static List asList(T... a)

It returns:

  • a fixed-size List as of size of a given array
  • an element of the same type as the one in the original array and it must be an Object
  • elements in the same order as in original array
  • a list that is serializable and implements RandomAccess

Since T is a varargs, we can pass an array or the items directly as parameters, and the method will create a fixed-size initialized list:

List<String> flowers = Arrays.asList("Ageratum", "Allium", "Poppy", "Catmint");

We can also pass an actual array:

String[] flowers = { "Ageratum", "Allium", "Poppy", "Catmint" };
List<String> flowerList = Arrays.asList(flowers);

Since the returned List is a fixed-size List, we can’t add/remove elements.

An attempt to add more elements would cause UnsupportedOperationException:

String[] flowers = { "Ageratum", "Allium", "Poppy", "Catmint" }; 
List<String> flowerList = Arrays.asList(flowers); 
flowerList.add("Celosia");

The root of this Exception is that the returned object doesn’t implement the add() operation since it isn’t the same as java.util.ArrayList.

It’s an ArrayList, from java.util.Arrays.

Another way to obtain the same exception is by trying to remove an element from the obtained list.

On the other hand, there are ways to obtain a mutable List in case we need it.

One of them is to create an ArrayList or any kind of list directly from the result of asList():

String[] flowers = { "Ageratum", "Allium", "Poppy", "Catmint" }; 
List<String> flowerList = new ArrayList<>(Arrays.asList(flowers));

3. Conclusion

In conclusion, it’s important to understand that adding more elements to a list can be problematic for more than just immutable lists.

As always, the full source code of the examples is available over on GitHub.

Conditionals in Thymeleaf

$
0
0

1. Overview

In this tutorial, we’re going to have a look at the different types of conditionals available in Thymeleaf.

For a quick introduction to Thymeleaf, please refer to this article.

2. Maven Dependencies

Let’s start with the Maven dependencies that are required to use Thymeleaf along with Spring:

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring4</artifactId>
    <version>3.0.9.RELEASE</version>
</dependency>

For other Spring releases, the matching thymeleaf-springX library should be used, where stands for Spring version. Please also note that Spring 5 is supported starting with 3.0.8.RELEASE, by Thymeleaf.

The latest versions of required dependencies can be found here.

3. Thymeleaf Conditionals

We have to distinguish between conditionals which allow us to render text within an HTML element depending on a condition and ones which control the instantiation of an HTML element itself.

Let’s define our Teacher model class which we’ll use throughout this article:

public class Teacher implements Serializable {
    private String gender;
    private boolean isActive;
    private List<String> courses = new ArrayList<>();
    private String additionalSkills;

3.1. Elvis Operator

The Elvis operator ?: lets us render text within an HTML element depending on the current state of a variable.

We can use default expressions to provide a default text if a variable is null:

<td th:text="${teacher.additionalSkills} ?: 'UNKNOWN'" />

In the upper example, we want to display the content of the teacher.additionalSkillsvariable if it is defined and we want the text “UNKNOWN” to be rendered otherwise.

It’s also possible to display arbitrary text depending on a boolean expression:

<td th:text="${teacher.active} ? 'ACTIVE' : 'RETIRED'" />

We can query a simple boolean variable as in the previous example, but string comparisons and range checks are possible as well.

The following comparators and their textual representations are supported> (gt), >= (ge), < (lt), <= (le), == (eq) and != (ne).

3.2. If – Unless

The th:ifandth:unless attributes allow us to render an HTML element depending on a provided condition:

<td>
    <span th:if="${teacher.gender == 'F'}">Female</span>
    <span th:unless="${teacher.gender == 'F'}">Male</span>
</td>

If the content of the teacher.gendervariable equals to an F,then the span element with the value “Female” is rendered.

Otherwise, the element with “Male” is rendered. Such a setup is comparable to an if-else clause present in most programming languages.

3.3. Switch – Case

If there’re more than two possible results of an expression, we can use the th:switch and th:case attributes for conditional rendering of the HTML elements:

<td th:switch="${#lists.size(teacher.courses)}">
    <span th:case="'0'">NO COURSES YET!</span>
    <span th:case="'1'" th:text="${teacher.courses[0]}"></span>
    <div th:case="*">
        <div th:each="course:${teacher.courses}" th:text="${course}"/>
    </div>
</td>

Depending on the size of theteacher.courseslist we either display a default text, the single course or all courses available. The asterisk (*)is used for the default option.

4. Conclusion

In this short article, we investigated the different types of Thymeleaf conditionals and presented some simplified examples showing the various options.

The examples can be found in the GitHub project.

Working with Fragments in Thymeleaf

$
0
0

1. Overview

In this tutorial, we’ll show how to make use of Thymeleaf Fragments to reuse some common parts of a site. After setting up a very simple Spring MVC project, we’ll focus on views.

If you’re new to Thymeleaf, you can check other articles on this site like this introduction, as well as this one about the 3.0 version of the engine.

2. Maven Dependencies

We’ll need a couple of dependencies to enable Thymeleaf:

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring4</artifactId>
    <version>3.0.9.RELEASE</version>
</dependency>

The latest version of thymeleaf and thymeleaf-spring4 can be found on Maven Central.

3. Spring Project

3.1. Spring MVC Configuration

To enable Thymeleaf and set the template suffix, we need to configure MVC with a view resolver and template resolver.

We’ll also set the directory for some static resources:

@Bean
public ViewResolver htmlViewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(templateEngine(htmlTemplateResolver()));
    resolver.setContentType("text/html");
    resolver.setCharacterEncoding("UTF-8");
    resolver.setViewNames(ArrayUtil.array("*.html"));
    return resolver;
}

private ITemplateResolver htmlTemplateResolver() {
    SpringResourceTemplateResolver resolver
      = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setCacheable(false);
    resolver.setTemplateMode(TemplateMode.HTML);
    return resolver;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**", "/css/**")
      .addResourceLocations("/WEB-INF/resources/", "/WEB-INF/css/");
}

Note that if we’re using Spring Boot, this configuration may not be necessary unless we need to apply our own customizations.

3.2. The Controller

In this case, the controller is just a vehicle for the views. Each view shows a different fragment use scenario.

The last one loads some data that is passed through the model to be displayed on the view:

@Controller
public class FragmentsController {

    @GetMapping("/fragments")
    public String getHome() {
        return "fragments.html";
    }

    @GetMapping("/markup")
    public String markupPage() {
        return "markup.html";
    }

    @GetMapping("/params")
    public String paramsPage() {
        return "params.html";
    }

    @GetMapping("/other")
    public String otherPage(Model model) {
        model.addAttribute("data", StudentUtils.buildStudents());
        return "other.html";
    }
}

Note that the view names must contain the “.html” suffix because of the way we configured our resolver. We’ll also specify the suffix when we refer to fragment names.

4. The Views

4.1. Simple Fragment Inclusion

First of all, we’ll use reuse common parts in our pages.

We can define these parts as fragments, either in isolated files or in a common page. In this project, these reusable parts are defined in a folder named fragments.

There are three basic ways to include content from a fragment:

  • insert – inserts content inside the tag
  • replace – replaces the current tag with the tag defining the fragment
  • include – this is deprecated but it may still appear in a legacy code

The next example, fragments.html, shows the use of all three ways. This Thymeleaf template adds fragments in the head and the body of the document:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf Fragments: home</title>
<!--/*/ <th:block th:include="fragments/general.html :: headerfiles">
        </th:block> /*/-->
</head>
<body>
    <header th:insert="fragments/general.html :: header"> </header>
    <p>Go to the next page to see fragments in action</p>
    <div th:replace="fragments/general.html :: footer"></div>
</body>
</html>

Now, let’s take a look at a page that holds some fragments. It’s called general.html, and it’s like a whole page with some parts defined as fragments ready to be used:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="headerfiles">
<meta charset="UTF-8" />
<link th:href="@{/css/styles.css}" rel="stylesheet">
</head>
<body>
    <div th:fragment="header">
        <h1>Thymeleaf Fragments sample</h1>
    </div>
    <p>Go to the next page to see fragments in action</p>
    <aside>
        <div>This is a sidebar</div>
    </aside>
    <div class="another">This is another sidebar</div>
    <footer th:fragment="footer">
        <a th:href="@{/fragments}">Fragments Index</a> | 
        <a th:href="@{/markup}">Markup inclussion</a> | 
        <a th:href="@{/params}">Fragment params</a> | 
        <a th:href="@{/other}">Other</a>
    </footer>
</body>
</html>

The <head> section contains just a stylesheet, but we could apply other tools such as Bootstrap, jQuery, or Foundation, either directly or using Webjars.

Note that all the reusable tags of this template have the attribute th:fragment, but next we’ll see how to include any other part of the page.

After the rendering and fragments inclusion, the returned content is:

<!DOCTYPE HTML>
<html>
<head>
<title>Thymeleaf Fragments: home</title>
<meta charset="UTF-8" />
<link href="/spring-thymeleaf/css/styles.css" rel="stylesheet">
</head>
<body>
    <header>
        <div>
            <h1>Thymeleaf Fragments sample</h1>
        </div>
    </header>
    <p>Go to the next page to see fragments in action</p>
    <footer>
        <a href="/spring-thymeleaf/fragments">Fragments Index</a> | 
        <a href="/spring-thymeleaf/markup">Markup inclussion</a> | 
        <a href="/spring-thymeleaf/params">Fragment params</a> | 
        <a href="/spring-thymeleaf/other">Other</a>
    </footer>
</body>
</html>

4.2. Markup Selectors for Fragments

One of the great things about Thymeleaf Fragments is that we can also grab any part of a template just using the simple selectors, through classes, ids, or simply by tags.

This page, for example, includes some components from general.html file: an aside block and the div.another block:

<body>
    <header th:insert="fragments/general.html :: header"> </header>
    <div th:replace="fragments/general.html :: aside"></div>
    <div th:replace="fragments/general.html :: div.another"></div>
    <div th:replace="fragments/general.html :: footer"></div>
</body>

4.3. Parametrized Fragments

We can pass parameters to a fragment in order to change some specific part of it. To do that, the fragment must be defined as a function call, where we must declare a list of parameters.

In this example, we define a fragment for a generic form field:

<div th:fragment="formField (field, value, size)">
    <div>
        <label th:for="${#strings.toLowerCase(field)}"> <span
            th:text="${field}">Field</span>
        </label>
    </div>
    <div>
        <input type="text" th:id="${#strings.toLowerCase(field)}"
            th:name="${#strings.toLowerCase(field)}" th:value="${value}"
            th:size="${size}">
    </div>
</div>

And here’s a simple use of that fragment where we pass parameters to it:

<body>
    <header th:insert="fragments/general.html :: header"> </header>
    <div th:replace="fragments/forms.html
      :: formField(field='Name', value='John Doe',size='40')">
    </div>
    <div th:replace="fragments/general.html :: footer"></div>
</body>

And this is how the returned field will look:

<div>
    <div>
        <label for="name"> <span>Name</span>
        </label>
    </div>
    <div>
        <input type="text" id="name"
        name="name" value="John Doe"
        size="40">
    </div>
</div>

4.4. Fragment Inclusion Expressions

Thymeleaf fragments offer other interesting options such as support for conditional expressions to determine whether to include a fragment.

Using the Elvis operator with any of the expressions provided by Thymeleaf (security, strings, and collections for example), we’re able to load different fragments.

For example, we can define this fragment with some content that we’ll show depending on a given condition. This could be a file containing different kinds of blocks:

<div th:fragment="dataPresent">Data received</div>
<div th:fragment="noData">No data</div>

And this is how we could load them with an expression:

<div
    th:replace="${#lists.size(data) > 0} ? 
        ~{fragments/menus.html :: dataPresent} : 
        ~{fragments/menus.html :: noData}">
</div>

To learn more about Thymeleaf Expressions, check our article here.

4.5. Flexible Layouts

The next example also shows two other interesting uses of fragments to render a table with data. This is the reusable table fragment, with two important parts: a table header that can be changed, and the body where data is rendered:

<table>
    <thead th:fragment="fields(theadFields)">
        <tr th:replace="${theadFields}">
        </tr>
    </thead>
    <tbody th:fragment="tableBody(tableData)">
        <tr th:each="row: ${tableData}">
            <td th:text="${row.id}">0</td>
            <td th:text="${row.name}">Name</td>
        </tr>
    </tbody>
    <tfoot>
    </tfoot>
</table>

When we want to use this table, we can pass our own table header using the fields function. The header is referenced with the class myFields. The table body is loaded by passing data as a parameter to the tableBody function:

<body>
    <header th:replace="fragments/general.html :: header"> </header>
    <table>
        <thead th:replace="fragments/tables.html
              :: fields(~{ :: .myFields})">
            <tr class="myFields">

                <th>Id</th>
                <th>Name</th>
            </tr>
        </thead>
        <div th:replace="fragments/tables.html
          :: tableBody(tableData=${data})">
        </div>
    </table>
    <div th:replace="fragments/general.html :: footer"></div>
</body>

And this is how the final page will look:

<body>
    <div>
        <h1>Thymeleaf Fragments sample</h1>
    </div>
    <div>Data received</div>
    <table>
        <thead>
            <tr class="myFields">

                <th>Id</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1001</td>
                <td>John Smith</td>
            </tr>
            <tr>
                <td>1002</td>
                <td>Jane Williams</td>
            </tr>
        </tbody>
    </table>
    <footer>
        <a href="/spring-thymeleaf/fragments">Fragments Index</a> |
        <a href="/spring-thymeleaf/markup">Markup inclussion</a> |
        <a href="/spring-thymeleaf/params">Fragment params</a> |
        <a href="/spring-thymeleaf/other">Other</a>
    </footer>
</body>

5. Conclusion

In this article, we’ve shown how to reuse view components through the use of Thymeleaf Fragments, a powerful tool that can make template management easier.

We have also presented some other interesting features that go beyond the basics. We should take these into account when choosing Thymeleaf as our view rendering engine.

If you want to learn about other Thymeleaf features, you should definitely take a look at our article about Layout Dialects.

As always, the complete implementation code of the example is available over on GitHub.

Spring Boot Change Context Path

$
0
0

1. Overview

Spring Boot, by default, serves content on the root context path (“/”).

And while, usually, it’s a good idea to prefer convention over configuration, there are cases when we do want to have a custom path.

In this quick tutorial, we’ll cover the different ways of configuring it.

2. Setting the Property

Just like many other configuration options, the context path in Spring Boot can be changed by setting a property, i.e., server.servlet.context-path.

Note that this works for Spring Boot 2.x.

For Boot 1.x, the property is server.context-path.

There are multiple ways of setting this property, let’s look at these one by one.

2.1. Using application.properties / yml

The most straightforward way of changing the context path is to set the property in the application.properties/yml file:

server.servlet.context-path=/baeldung

Instead of putting the properties file in src/main/resources, we can also keep it in the current working directory (outside of the classpath).

2.2. Java System Property

We can also set the context path as a Java system property before even the context is initialized:

public static void main(String[] args) {
    System.setProperty("server.servlet.context-path", "/baeldung");
    SpringApplication.run(Application.class, args);
}

2.3. OS Environment Variable

Spring Boot can also rely on OS environment variables. On Unix based systems we can write:

$ export SERVER_SERVLET_CONTEXT_PATH=/baeldung

On Windows, the command to set an environment variable is:

> set SERVER_SERVLET_CONTEXT_PATH=/baeldung

The above environment variable is for Spring Boot 2.x.xIf we have 1.x.x, the variable is SERVER_CONTEXT_PATH.

2.4. Command Line Arguments

We can set the properties dynamically via command line arguments as well:

$ java -jar app.jar --server.servlet.context-path=/baeldung

3. Using Java Config

Now let’s set the context path by populating the bean factory with a configuration bean.

With Spring Boot 2, we can use WebServerFactoryCustomizer:

@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>
  webServerFactoryCustomizer() {
    return factory -> factory.setContextPath("/baeldung");
}

With Spring Boot 1, we can create an instance of EmbeddedServletContainerCustomizer:

@Bean
public EmbeddedServletContainerCustomizer
  embeddedServletContainerCustomizer() {
    return container -> container.setContextPath("/baeldung");
}

4. Priority Order of Configurations

With this many options, we may end up having more than one configuration for the same property.

Here’s the priority order in descending order, which Spring Boot uses to select the effective configuration:

  1. Java Config
  2. Command Line Arguments
  3. Java System Properties
  4. OS Environment Variables
  5. application.properties in Current Directory
  6. application.properties in the classpath (src/main/resources or the packaged jar file)

5. Conclusion

In this article, we quickly covered different ways of setting the context path, or any other configuration property, in a Spring Boot application.

@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll

$
0
0

1. Introduction

In this short tutorial, we’re going to explain the differences between the @Before, @BeforeClass, @BeforeEach and @BeforeAll annotations in JUnit 4 and 5 – with practical examples of how to use them.

We’ll also cover briefly their @After complementary annotations.

Let’s start with JUnit 4.

2. @Before

Methods annotated with the @Before annotation are executed before each test. This is useful when we want to execute some common code before running a test.

Let’s see an example where we initialize a list and add some values:

@RunWith(JUnit4.class)
public class BeforeAndAfterAnnotationsTest {

    // ...

    private List<String> list;

    @Before
    public void init() {
        LOG.info("startup");
        list = new ArrayList<>(Arrays.asList("test1", "test2"));
    }

    @After
    public void finalize() {
        LOG.info("finalize");
        list.clear();
    }
}

Notice that we also added another method annotated with @After in order to clear the list after the execution of each test.

After that, let’s add some tests to check the size of our list:

@Test
public void whenCheckingListSize_thenSizeEqualsToInit() {
    LOG.info("executing test");
    assertEquals(2, list.size());

    list.add("another test");
}

@Test
public void whenCheckingListSizeAgain_thenSizeEqualsToInit() {
    LOG.info("executing another test");
    assertEquals(2, list.size());

    list.add("yet another test");
}

In this case, it’s crucial to make sure that test environment is properly set up before running each test since the list is modified during every test execution.

If we take a look at the log output we can check that the init and finalize methods were executed once per test:

... startup
... executing another test
... finalize
... startup
... executing test
... finalize

3. @BeforeClass

When we want to execute an expensive common operation before each test, it’s preferable to execute it only once before running all tests using @BeforeClass. Some examples of common expensive operations are the creation of a database connection or the startup of a server.

Let’s create a simple test class that simulates the creation of a database connection:

@RunWith(JUnit4.class)
public class BeforeClassAndAfterClassAnnotationsTest {

    // ...
    
    @BeforeClass
    public static void setup() {
        LOG.info("startup - creating DB connection");
    }

    @AfterClass
    public static void tearDown() {
        LOG.info("closing DB connection");
    }
}

Notice that these methods have to be static, so they’ll be executed before running the tests of the class.

As we did before, let’s also add some simple tests:

@Test
public void simpleTest() {
    LOG.info("simple test");
}

@Test
public void anotherSimpleTest() {
    LOG.info("another simple test");
}

This time, if we take a look at the log output we can check that the setup and tearDown methods were executed only once:

... startup - creating DB connection
... simple test
... another simple test
... closing DB connection

4. @BeforeEach and @BeforeAll

@BeforeEach and @BeforeAll are the JUnit 5 equivalents of @Before and @BeforeClass. These annotations were renamed with clearer names to avoid confusion.

Let’s duplicate our previous classes using these new annotations, starting with the @BeforeEach and @AfterEach annotations:

@RunWith(JUnitPlatform.class)
class BeforeEachAndAfterEachAnnotationsTest {

    // ...
    
    private List<String> list;
    
    @BeforeEach 
    void init() {
        LOG.info("startup");
        list = new ArrayList<>(Arrays.asList("test1", "test2"));
    }

    @AfterEach
    void finalize() {
        LOG.info("finalize");
        list.clear();
    }

    // ...
}

If we check logs, we can confirm that it works in the same way as with the @Before and @After annotations:

... startup
... executing another test
... finalize
... startup
... executing test
... finalize

Finally, let’s do the same with the other test class to see the @BeforeAll and @AfterAll annotations in action:

@RunWith(JUnitPlatform.class)
public class BeforeAllAndAfterAllAnnotationsTest {

    // ...
    
    @BeforeAll
    public static void setup() {
        LOG.info("startup - creating DB connection");
    }

    @AfterAll
    public static void tearDown() {
        LOG.info("closing DB connection");
    }

    // ...
}

And the output is the same as with the old annotation:

... startup - creating DB connection
... simple test
... another simple test
... closing DB connection

5. Conclusion

In this article, we showed the differences between the @Before, @BeforeClass, @BeforeEach and @BeforeAll annotations in JUnit and when each of them should be used.

As always, the full source code of the examples is available over on GitHub.


Facade Design Pattern in Java

$
0
0

1. Introduction

In this quick tutorial, we’re going to take a look at one of the structural design patterns: the Facade.

First, we’ll give an overview of the pattern, list its benefits and describe what problems it solves.

Then, we’ll apply the facade pattern to an existing, practical problem with Java.

2. What is a Facade?

Simply put, a facade encapsulates a complex subsystem behind a simple interface. It hides much of the complexity and makes the subsystem easy to use.

Also, if we need to use the complex subsystem directly, we still can do that; we aren’t forced to use the facade all the time.

Besides a much simpler interface, there’s one more benefit of using this design pattern. It decouples a client implementation from the complex subsystem. Thanks to this, we can make changes to the existing subsystem and don’t affect a client.

Let’s see the facade in action.

3. Example

Let’s say that we want to start a car. The following diagram represents the legacy system, which allows us to do so:

 

As you can see, it can be quite complex and does require some effort to start the engine correctly:

airFlowController.takeAir()
fuelInjector.on()
fuelInjector.inject()
starter.start()
coolingController.setTemperatureUpperLimit(DEFAULT_COOLING_TEMP)
coolingController.run()
catalyticConverter.on()

Similarly, stopping the engine also requires quite a few steps:

fuelInjector.off()
catalyticConverter.off()
coolingController.cool(MAX_ALLOWED_TEMP)
coolingController.stop()
airFlowController.off()

A facade is just what we need here. We’ll hide all the complexity in two methods: startEngine() and stopEngine().

Let’s see how we can implement it:

public class CarEngineFacade {
    private static int DEFAULT_COOLING_TEMP = 90;
    private static int MAX_ALLOWED_TEMP = 50;
    private FuelInjector fuelInjector = new FuelInjector();
    private AirFlowController airFlowController = new AirFlowController();
    private Starter starter = new Starter();
    private CoolingController coolingController = new CoolingController();
    private CatalyticConverter catalyticConverter = new CatalyticConverter();

    public void startEngine() {
        fuelInjector.on();
        airFlowController.takeAir();
        fuelInjector.on();
        fuelInjector.inject();
        starter.start();
        coolingController.setTemperatureUpperLimit(DEFAULT_COOLING_TEMP);
        coolingController.run();
        catalyticConverter.on();
    }

    public void stopEngine() {
        fuelInjector.off();
        catalyticConverter.off();
        coolingController.cool(MAX_ALLOWED_TEMP);
        coolingController.stop();
        airFlowController.off();
    }

Now, to start and stop a car, we need only 2 lines of code, instead of 13:

facade.startEngine();
// ...
facade.stopEngine();

4. Drawbacks

The facade pattern doesn’t force us to unwanted tradeoffs, because it only adds additional layers of abstraction.

Sometimes the pattern can be overused in simple scenarios, which will lead to redundant implementations.

5. Conclusion

In this article, we’ve explained the facade pattern and demonstrated how to implement it atop of an existing system.

The implementation of these examples can be found over on GitHub.

Servlet Redirect vs Forward

$
0
0

1. Overview

Occasionally, the initial HTTP Request Handler in our Java Servlet needs to delegate the Request to another resource. In these cases, we can either forward the request further or redirect it to a different resource.

We’ll use both mechanisms and discuss differences and best practices of each.

2. Maven Dependencies

First, let’s add the Servlet Maven dependency:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.0</version>
</dependency>

The latest version can be found here.

3. Forward

Let’s now jump right in and have a look at how to do a simple forward:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
    RequestDispatcher dispatcher = getServletContext()
      .getRequestDispatcher("/forwarded");
    dispatcher.forward(req, resp);
}

We get hold of RequestDispatcher reference from parent Servlet and point it to another server resource.

Simply put, this will forward the request.

When a client submits a request to http://localhost:8081/hello?name=Dennis, this logic will run and the request will be forwarded to “/forwarded“.

4. Redirect

Now that we understand the concept of forwarding, let’s have a look at a quick snippet for redirecting:

protected void doGet(HttpServletRequest req, HttpServletResponse resp){
    resp.sendRedirect(req.getContextPath() + "/redirected");
}

We use original response object to redirect this request to another URL: “/redirected”.

When a client submits a request to http://localhost:8081/welcome?name=Dennis, the request will be redirected to http://localhost:8081/redirected.

To find out more about doing redirects in the context of Spring, have a look at our dedicated article here.

5. Differences

We passed the parameter “name” with a value in both cases. Simply put, forwarded requests still carry this value, but redirected requests don’t.

This is because, with a redirect, the request object is different from the original one. If we still want use this parameter, we need to save it in the HttpSession object.

Here is a list of major differences between servlet forward and redirect:

Forward:

  • The request will be further processed on the server side
  • The client isn’t impacted by forward, URL in a browser stays the same
  • Request and response objects will remain the same object after forwarding. Request-scope objects will be still available

Redirect:

  • The request is redirected to a different resource
  • The client will see the URL change after the redirect
  • A new request is created
  • Redirect is normally used within Post/Redirect/Get web development pattern

6. Conclusion

Forwarding and redirecting are both about sending a user to different resources, although they have quite different semantics.

Picking between these is simple. If the previous scope is required, or the user doesn’t need to be informed, but the application also wants to perform an internal action then use forwarding.

To discard the scope or if the new content isn’t associated with the original request – such as a redirect to a login page or completing a form submission – then use redirecting.

As always, the example code can be found over on GitHub.

Spring Boot: Configuring a Main Class

$
0
0

1. Overview

This quick tutorial provides different ways of defining an entry point into a Spring Boot application via Maven and Gradle.

A Spring Boot application’s main class is a class that contains a public static void main() method that starts up the Spring ApplicationContext. By default, if the main class isn’t explicitly specified, Spring will search for one in the classpath at compile time and fail to start if none or multiple of them are found.

Unlike in conventional Java applications, the main class discussed in this tutorial does not appear as the Main-Class metadata property in META-INF/MANIFEST.MF of the resulting JAR or WAR file.

Spring Boot expects the artifact’s Main-Class metadata property to be set to org.springframework.boot.loader.JarLauncher (or WarLauncher) which means that passing our main class directly to the java command line won’t start our Spring Boot application correctly.

An example manifest looks like this:

Manifest-Version: 1.0
Start-Class: org.baeldung.DemoApplication
Main-Class: org.springframework.boot.loader.JarLauncher

Instead, we need to define the Start-Class property in the manifest which is evaluated by JarLauncher to start the application.

Let’s see how we can control this property using Maven and Gradle.

2. Maven

The main class can be defined as a start-class element in the pom.xml‘s properties section:

<properties>
      <!-- The main class to start by executing "java -jar" -->
      <start-class>org.baeldung.DemoApplication</start-class>
</properties>

Note that this property will only be evaluated if we also add the spring-boot-starter-parent as <parent> in our pom.xml.

Alternatively, the main class can be defined as the mainClass element of the spring-boot-maven-plugin in the plugin section of our pom.xml:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>             
            <configuration>    
                <mainClass>org.baeldung.DemoApplication</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

An example of this Maven configuration can be found over on GitHub.

3. Gradle

If we’re using the Spring Boot Gradle plugin, there are a few configurations inherited from org.springframework.boot where we could specify our main class.

In the project’s Gradle file, mainClassName can be defined within springBoot configuration block. This change made here is picked up by bootRun and bootJar task:

springBoot {
    mainClassName = 'org.baeldung.DemoApplication'
}

Alternatively, the main class can be defined as the mainClassName property of bootJar Gradle task:

bootJar {
    mainClassName = 'org.baeldung.DemoApplication'
}

Or as a manifest attribute of the bootJar task:

bootJar {
    manifest {
	attributes 'Start-Class': 'org.baeldung.DemoApplication'
    }
}

Note that the main class specified in the bootJar configuration block only affects the JAR that the task itself produces. The change doesn’t affect the behavior of other Spring Boot Gradle tasks such as bootRun.

As a bonus, if the Gradle application plugin is applied to the project, mainClassName can be defined as a global property:

mainClassName = 'org.baeldung.DemoApplication'

We can find an example of these Gradle configurations over on GitHub.

4. Using CLI

We can also specify a main class via the command line interface.

Spring Boot’s org.springframework.boot.loader.PropertiesLauncher comes with a JVM argument to let you override the logical main-class called loader.main:

java -cp bootApp.jar -Dloader.main=org.baeldung.DemoApplication org.springframework.boot.loader.PropertiesLauncher

5. Conclusion

There are more than a few ways to specify the entry point to a Spring Boot application. It’s important to know that all these configurations are just different ways to modify the manifest of a JAR or WAR file.

Working code examples can be found here and here.

Obtaining Auto-generated Keys in Spring JDBC

$
0
0

1. Introduction

In this quick tutorial, we’ll explore the possibility of getting the auto-generated key after inserting entities when working with Spring JDBC.

2. Maven Dependencies

At first, we need to have spring-boot-starter-jdbc and H2 dependencies defined in our pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

We can check out the latest version of those two dependencies on Maven Central: spring-boot-starter-jdbc and h2.

3. Getting the Auto-Generated Key

3.1. The Scenario

Let’s define a sys_message table which has 2 columns: id (auto-generated key) and message:

CREATE TABLE IF NOT EXISTS sys_message (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    message varchar(100) NOT NULL,
    PRIMARY KEY (id)
);

3.2. Using the JdbcTemplate

Now, let’s implement a method which will use JDBCTemplate to insert the new record and return the auto-generated id. 

Therefore, we’ll use the JDBCTemplate update() method which supports the retrieval of primary keys generated by the database. This method takes an instance of the PrepareStatementCreator interface as the first argument and the other argument is the KeyHolder. 

Since the PrepareStatementCreator interface is a FunctionalInterface where its method accepts an instance of java.sql.Connection and return a java.sql.PreparedStatement object, for simplicity, we can use a lambda expression:

String INSERT_MESSAGE_SQL 
  = "insert into sys_message (message) values(?) ";
    
public long insertMessage(String message) {    
    KeyHolder keyHolder = new GeneratedKeyHolder();

    jdbcTemplate.update(connection -> {
        PreparedStatement ps = connection
          .prepareStatement(INSERT_MESSAGE_SQL);
          ps.setString(1, message);
          return ps;
        }, keyHolder);

        return (long) keyHolder.getKey();
    }
}

It’s worth noting that the keyHolder object will contain the auto-generated key return from the JDBCTemplate update() method.

We can retrieve that key by calling keyHolder.getKey().

Besides, we can verify the method:

@Test
public void 
  insertJDBC_whenLoadMessageByKey_thenGetTheSameMessage() {
    long key = messageRepositoryJDBCTemplate.insert(MESSAGE_CONTENT);
    String loadedMessage = messageRepositoryJDBCTemplate
      .getMessageById(key);

    assertEquals(MESSAGE_CONTENT, loadedMessage);
}

3.3. Using SimpleJdbcInsert

In addition to the JDBCTemplate, we also can use SimpleJdbcInsert to achieve the same result.

Hence, we need to initialize an instance of the SimpleJdbcInsert:

@Repository
public class MessageRepositorySimpleJDBCInsert {

    SimpleJdbcInsert simpleJdbcInsert;

    @Autowired
    public MessageRepositorySimpleJDBCInsert(DataSource dataSource) {
        simpleJdbcInsert = new SimpleJdbcInsert(dataSource)
          .withTableName("sys_message").usingGeneratedKeyColumns("id");
    }
    
    //...
}

Consequently, we can call the executeAndReturnKey method of the SimpleJdbcInsert to insert a new record to sys_message table and get back the auto-generated key:

public long insert(String message) {
    Map<String, Object> parameters = new HashMap<>(1);
    parameters.put("message", message);
    Number newId = simpleJdbcInsert.executeAndReturnKey(parameters);
    return (long) newId;
}

Furthermore, we can verify that method quite simply:

@Test
public void 
  insertSimpleInsert_whenLoadMessageKey_thenGetTheSameMessage() {
    long key = messageRepositorySimpleJDBCInsert.insert(MESSAGE_CONTENT);
    String loadedMessage = messageRepositoryJDBCTemplate.getMessageById(key);

    assertEquals(MESSAGE_CONTENT, loadedMessage);
}

4. Conclusion

We’ve explored the possibility of using JDBCTemplate and SimpleJdbcInsert for inserting a new record and getting the auto-generated key back.

As always, we can find the implementation of this article over on Github.

Using the JetS3t Java Client With Amazon S3

$
0
0

1. Overview

In this tutorial, we’ll use the JetS3t library with Amazon S3.

Simply put, we’ll create buckets, write data to them, read data back, copy it, and then list and delete them.

2. JetS3t Setup

2.1. Maven Dependency

First, we need to add the NATS library and Apache HttpClient to our pom.xml:

<dependency>
    <groupId>org.lucee</groupId>
    <artifactId>jets3t</artifactId>
    <version>0.9.4.0006L</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.5</version>
</dependency>

Maven Central has the latest version of the JetS3t library and the latest version of HttpClient. The source for JetS3t can be found here.

We’ll be using Apache Commons Codec for one of our tests, so we’ll add that to our pom.xml too:

<dependency>
    <groupId>org.lucee</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10.L001</version>
</dependency>

Maven Central has the latest version here.

2.2. Amazon AWS Keys

We’ll need AWS Access Keys to connect to the S3 storage service. A free account can be created here.

After we have an account, we need to create a set of security keys.There’s documentation about users and access keys available here.

JetS3t using Apache Commons logging, so we’ll use it too when we want to print information about what we’re doing.

3. Connecting to a Simple Storage

Now that we have an AWS access key and secret key, we can connect to S3 storage.

3.1. Connecting to AWS

First, we create AWS credentials and then use them to connect to the service:

AWSCredentials awsCredentials 
  = new AWSCredentials("access key", "secret key");
s3Service = new RestS3Service(awsCredentials);

RestS3Serviceis our connection to Amazon S3.It uses HttpClientto communicate with S3 over REST.

3.2. Verifying Connection

We can verify that we’ve successfully connected to the service by listing buckets:

S3Bucket[] myBuckets = s3Service.listAllBuckets();

Depending on whether or not we’ve created buckets before, the array may be empty, but if the operation doesn’t throw an exception, we have a valid connection.

4. Buckets Management

With a connection to Amazon S3, we can create buckets to hold our data. S3 is an object storage system. Data is uploaded as objects and stored in buckets.

Since all S3 buckets share the same global namespace, each one must have a unique name.

4.1. Creating a Bucket

Let’s try to create a bucket name “mybucket“:

S3Bucket bucket = s3Service.createBucket("mybucket");

This fails with an exception:

org.jets3t.service.S3ServiceException: Service Error Message.
  -- ResponseCode: 409, ResponseStatus: Conflict, XML Error Message:
  <!--?xml version="1.0" encoding="UTF-8"?-->
  <code>BucketAlreadyExists</code> The requested bucket name is not available. 
  The bucket namespace is shared by all users of the system.
  Please select a different name and try again.
  mybucket 07BE34FF3113ECCF 
at org.jets3t.service.S3Service.createBucket(S3Service.java:1586)

The name “mybucket” is, predictably, already taken. For the rest of the tutorial, we’ll make up our names.

Let’s try again with a different name:

S3Bucket bucket = s3Service.createBucket("myuniquename");
log.info(bucket);

With a unique name, the call succeeds, and we see information about our bucket:

[INFO] JetS3tClient - S3Bucket
[name=myuniquename,location=US,creationDate=Sat Mar 31 16:47:47 EDT 2018,owner=null]

4.2. Deleting a Bucket

Deleting a bucket is as easy as creating it, except for one thing; buckets must be empty before they can be removed!

s3Service.deleteBucket("myuniquename");

This will throw an exception for a bucket that is not empty.

4.3. Specifying the Bucket Region

Buckets can be created in a specific data center.For JetS3t the default is Northern Virginia in the United States, or “us-east-1.”

We can override this by specifying a different region:

S3Bucket euBucket 
  = s3Service.createBucket("eu-bucket", S3Bucket.LOCATION_EUROPE);
S3Bucket usWestBucket = s3Service
  .createBucket("us-west-bucket", S3Bucket.LOCATION_US_WEST);
S3Bucket asiaPacificBucket = s3Service
  .createBucket("asia-pacific-bucket", S3Bucket.LOCATION_ASIA_PACIFIC);

JetS3t has an extensive list of regions defined as constants.

5. Upload, Download, and Delete Data

Once we have a bucket, we can add objects to it. Buckets are intended to be long-lasting, and there’s no hard limit on the size or number of objects a bucket can contain.

Data is uploaded to S3 by creating S3Objects.We can upload data a from an InputStream,but JetS3t also provides convenience methods for Stringsand Files.

5.1. StringData

Let’s take a look at Stringsfirst:

S3Object stringObject = new S3Object("object name", "string object");
s3Service.putObject("myuniquebucket", stringObject);

Similar to buckets, objects have names, however, object names only live inside their buckets, so we don’t have to worry about them being globally unique.

We create the object by passing a name and the data to the constructor. Then we store it with putObject.

When we use this method to store Stringswith JetS3t, it sets the correct content type for us.

Let’s query S3 for information about our object and look at the content type:

StorageObject objectDetailsOnly 
  = s3Service.getObjectDetails("myuniquebucket", "my string");
log.info("Content type: " + objectDetailsOnly.getContentType() + " length: " 
  + objectDetailsOnly.getContentLength());

ObjectDetailsOnly()retrieves the objects metadata without downloading it. When we log the content type we see:

[INFO] JetS3tClient - Content type: text/plain; charset=utf-8 length: 9

JetS3t identified the data as text and set the length for us.

Let’s download the data and compare it to what we uploaded:

S3Object downloadObject = 
  s3Service.getObject("myuniquebucket, "string object");
String downloadString = new BufferedReader(new InputStreamReader(
  object.getDataInputStream())).lines().collect(Collectors.joining("\n"));
 
assertTrue("string object".equals(downloadString));

Data is retrieved in the same S3Objectwe use to upload it, with the bytes available in a DataInputStream.

5.2. File Data

The process for uploading files is similar to Strings:

File file = new File("src/test/resources/test.jpg");
S3Object fileObject = new S3Object(file);
s3Service.putObject("myuniquebucket", fileObject);

When S3Objectsare passed a Filethey derive their name from the base name of the files they contain:

[INFO] JetS3tClient - File object name is test.jpg

JetS3t takes the Fileand uploads it for us.It will attempt to load a mime.types filefrom the classpath and use it to identify the type of file and sent content type appropriately.

If we retrieve the object info of our file upload and get the content type we see:

[INFO] JetS3tClient - Content type:application/octet-stream

Let’s download our file to a new one and compare the contents:

String getFileMD5(String filename) throws IOException {
    try (FileInputStream fis = new FileInputStream(new File(filename))) {
        return DigestUtils.md5Hex(fis);
    }
}

S3Object fileObject = s3Service.getObject("myuniquebucket", "test.jpg"); 
File newFile = new File("/tmp/newtest.jpg"); 
Files.copy(fileObject.getDataInputStream(), newFile.toPath(), 
  StandardCopyOption.REPLACE_EXISTING);
String origMD5 = getFileMD5("src/test/resources/test.jpg");
String newMD5 = getFileMD5("src/test/resources/newtest.jpg");
assertTrue(origMD5.equals(newMD5));

Similar to Stringswe downloaded the object and used the DataInputStream to create a new file. Then we calculated an MD5 hash for both files and compared them.

5.3. Streaming Data

When we upload objects other than Stringsor Files,we have a bit more work to do:

ArrayList<Integer> numbers = new ArrayList<>();
// adding elements to the ArrayList

ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(bytes);
objectOutputStream.writeObject(numbers);

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes.toByteArray());

S3Object streamObject = new S3Object("stream");
streamObject.setDataInputStream(byteArrayInputStream);
streamObject.setContentLength(byteArrayInputStream.available());
streamObject.setContentType("binary/octet-stream");

s3Service.putObject(BucketName, streamObject);

We need to set our content type and length before uploading.

Retrieving this stream means reversing the process:

S3Object newStreamObject = s3Service.getObject(BucketName, "stream");

ObjectInputStream objectInputStream = new ObjectInputStream(
  newStreamObject.getDataInputStream());
ArrayList<Integer> newNumbers = (ArrayList<Integer>) objectInputStream
  .readObject();

assertEquals(2, (int) newNumbers.get(0));
assertEquals(3, (int) newNumbers.get(1));
assertEquals(5, (int) newNumbers.get(2));
assertEquals(7, (int) newNumbers.get(3));

For different data types, the content type property can be used to select a different method for decoding the object.

6. Copying, Moving and Renaming Data

6.1. Copying Objects

Objects can be copied inside S3, without retrieving them.

Let’s copy our test file from section 5.2, and verify the result:

S3Object targetObject = new S3Object("testcopy.jpg");
s3Service.copyObject(
  BucketName, "test.jpg", 
  "myuniquebucket", targetObject, false);
S3Object newFileObject = s3Service.getObject(
  "myuniquebucket", "testcopy.jpg");

File newFile = new File("src/test/resources/testcopy.jpg");
Files.copy(
  newFileObject.getDataInputStream(), 
  newFile.toPath(), 
  REPLACE_EXISTING);
String origMD5 = getFileMD5("src/test/resources/test.jpg");
String newMD5 = getFileMD5("src/test/resources/testcopy.jpg");
 
assertTrue(origMD5.equals(newMD5));

We can copy objects inside the same bucket, or between two different ones.

If the last argument is true, the copied object will receive new metadata. Otherwise, it will retain the source object’s metadata.

If we want to modify the metadata, we can set the flag to true:

targetObject = new S3Object("testcopy.jpg");
targetObject.addMetadata("My_Custom_Field", "Hello, World!");
s3Service.copyObject(
  "myuniquebucket", "test.jpg", 
  "myuniquebucket", targetObject, true);

6.2. Moving Objects

Objects can be moved to another S3 bucket in the same region.A move operation is a copy then a delete operation.

If the copy operation fails, the source object isn’t deleted. If the delete operation fails, the object will still exist in the source and also in the destination location.

Moving an object looks similar to copying it:

s3Service.moveObject(
  "myuniquebucket",
  "test.jpg",
  "myotheruniquebucket",
  new S3Object("spidey.jpg"),
  false);

6.3. Renaming Objects

JetS3t has a convenience method for renaming objects.  To change an objects name we merely call it with a new S3Object:

s3Service.renameObject(
  "myuniquebucket", "test.jpg", new S3Object("spidey.jpg"));

7. Conclusion

In this tutorial, we used JetS3t to connect to Amazon S3. We created and deleted buckets. Then we added different types of data to buckets and retrieved the data. To wrap things up, we copied and moved our data.

Code samples, as always, can be found over on GitHub.

Viewing all 3850 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>