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

Introduction to Java 9 StackWalking API

$
0
0

1. Introduction

In this quick article, we will have a look at Java 9’s StackWalking API.

The new functionality provides access to a Stream of StackFrames, allowing us to easily browse stack in both directly and making good use of the powerful Stream API in Java 8.

2. Advantages of a StackWalker

In Java 8, the Throwable::getStackTrace and Thread::getStackTrace returns an array of StackTraceElements. Without a lot of manual code, there was no way to discard the unwanted frames and keep only the ones we are interested in.

In addition to this, the Thread::getStackTrace may return a partial stack trace. This is because the specification allows the VM implementation to omit some stack frames for the sake of performance.

In Java 9, using the walk() method of the StackWalker, we can traverse a few frames that we are interested in or the complete stack trace.

Of course, the new functionality is thread-safe; this allows multiple threads to share a single StackWalker instance for accessing their respective stacks.

As descriebed in the JEP-259, the JVM will be enhanced to allow efficient lazy access to additional stack frames when required.

3. StackWalker in Action

Let’s start by creating a class containing a chain of method calls:

public class StackWalkerDemo {

    public void methodOne() {
        this.methodTwo();
    }

    public void methodTwo() {
        this.methodThree();
    }

    public void methodThree() {
        // stack walking code
    }
}

3.1. Capture the Entire Stack Trace

Let’s move ahead and add some stack walking code:

public void methodThree() {
    List<StackFrame> stackTrace = StackWalker.getInstance()
      .walk(this::walkExample);
}

The StackWalker::walk method accepts a functional reference, creates a Stream of StackFrames for the current thread, applies the function to the Stream, and closes the Stream.

Now let’s define the StackWalkerDemo::walkExample method:

public List<StackFrame> walkExample(Stream<StackFrame> stackFrameStream) {
    return stackFrameStream.collect(Collectors.toList());
}

This method simply collects the StackFrames and returns it as a List<StackFrame>. To test this example, please run a JUnit test:

@Test
public void giveStalkWalker_whenWalkingTheStack_thenShowStackFrames() {
    new StackWalkerDemo().methodOne();
}

The only reason to run it as a JUnit test is to have more frames in our stack:

class com.baeldung.java9.stackwalker.StackWalkerDemo#methodThree, Line 20
class com.baeldung.java9.stackwalker.StackWalkerDemo#methodTwo, Line 15
class com.baeldung.java9.stackwalker.StackWalkerDemo#methodOne, Line 11
class com.baeldung.java9.stackwalker
  .StackWalkerDemoTest#giveStalkWalker_whenWalkingTheStack_thenShowStackFrames, Line 9
class org.junit.runners.model.FrameworkMethod$1#runReflectiveCall, Line 50
class org.junit.internal.runners.model.ReflectiveCallable#run, Line 12
  ...more org.junit frames...
class org.junit.runners.ParentRunner#run, Line 363
class org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference#run, Line 86
  ...more org.eclipse frames...
class org.eclipse.jdt.internal.junit.runner.RemoteTestRunner#main, Line 192

In the entire stack trace, we are only interested in top four frames. The remaining frames from org.junit and org.eclipse are nothing but noise frames.

3.2. Filtering the StackFrames

Let’s enhance our stack walking code and remove the noise:

public List<StackFrame> walkExample2(Stream<StackFrame> stackFrameStream) {
    return stackFrameStream
      .filter(f -> f.getClassName().contains("com.baeldung"))
      .collect(Collectors.toList());
}

Using the power of the Stream API, we are keeping only the frames that we are interested in. This will clear out the noise, leaving the top four lines in the stack log:

class com.baeldung.java9.stackwalker.StackWalkerDemo#methodThree, Line 27
class com.baeldung.java9.stackwalker.StackWalkerDemo#methodTwo, Line 15
class com.baeldung.java9.stackwalker.StackWalkerDemo#methodOne, Line 11
class com.baeldung.java9.stackwalker
  .StackWalkerDemoTest#giveStalkWalker_whenWalkingTheStack_thenShowStackFrames, Line 9

Let’s now identify the JUnit test that initiated the call:

public String walkExample3(Stream<StackFrame> stackFrameStream) {
    return stackFrameStream
      .filter(frame -> frame.getClassName()
        .contains("com.baeldung") && frame.getClassName().endsWith("Test"))
      .findFirst()
      .map(f -> f.getClassName() + "#" + f.getMethodName() 
        + ", Line " + f.getLineNumber())
      .orElse("Unknown caller");
}

Please note that here, we are only interested in a single StackFrame, which is mapped to a String. The output will only be the line containing StackWalkerDemoTest class.

3.3. Capturing the Reflection Frames

In order to capture the reflection frames, which are hidden by default, the StackWalker needs to be configured with an additional option SHOW_REFLECT_FRAMES:

List<StackFrame> stackTrace = StackWalker
  .getInstance(StackWalker.Option.SHOW_REFLECT_FRAMES)
  .walk(this::walkExample);

Using this option, all the reflections frames including Method.invoke() and Constructor.newInstance() will be captured:

com.baeldung.java9.stackwalker.StackWalkerDemo#methodThree, Line 40
com.baeldung.java9.stackwalker.StackWalkerDemo#methodTwo, Line 16
com.baeldung.java9.stackwalker.StackWalkerDemo#methodOne, Line 12
com.baeldung.java9.stackwalker
  .StackWalkerDemoTest#giveStalkWalker_whenWalkingTheStack_thenShowStackFrames, Line 9
jdk.internal.reflect.NativeMethodAccessorImpl#invoke0, Line -2
jdk.internal.reflect.NativeMethodAccessorImpl#invoke, Line 62
jdk.internal.reflect.DelegatingMethodAccessorImpl#invoke, Line 43
java.lang.reflect.Method#invoke, Line 547
org.junit.runners.model.FrameworkMethod$1#runReflectiveCall, Line 50
  ...eclipse and junit frames...
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner#main, Line 192

As we can see, the jdk.internal frames are the new ones captured by SHOW_REFLECT_FRAMES option.

3.4. Capturing Hidden Frames

In addition to the reflection frames, a JVM implementation may choose to hide implementation specific frames.

However, those frames are not hidden from the StackWalker:

Runnable r = () -> {
    List<StackFrame> stackTrace2 = StackWalker
      .getInstance(StackWalker.Option.SHOW_HIDDEN_FRAMES)
      .walk(this::walkExample);
    printStackTrace(stackTrace2);
};
r.run();

Note that we are assigning a lambda reference to a Runnable in this example. The only reason is that JVM will create some hidden frames for the lambda expression.

This is clearly visible in the stack trace:

com.baeldung.java9.stackwalker.StackWalkerDemo#lambda$0, Line 47
com.baeldung.java9.stackwalker.StackWalkerDemo$$Lambda$39/924477420#run, Line -1
com.baeldung.java9.stackwalker.StackWalkerDemo#methodThree, Line 50
com.baeldung.java9.stackwalker.StackWalkerDemo#methodTwo, Line 16
com.baeldung.java9.stackwalker.StackWalkerDemo#methodOne, Line 12
com.baeldung.java9.stackwalker
  .StackWalkerDemoTest#giveStalkWalker_whenWalkingTheStack_thenShowStackFrames, Line 9
jdk.internal.reflect.NativeMethodAccessorImpl#invoke0, Line -2
jdk.internal.reflect.NativeMethodAccessorImpl#invoke, Line 62
jdk.internal.reflect.DelegatingMethodAccessorImpl#invoke, Line 43
java.lang.reflect.Method#invoke, Line 547
org.junit.runners.model.FrameworkMethod$1#runReflectiveCall, Line 50
  ...junit and eclipse frames...
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner#main, Line 192

The top two frames are the lambda proxy frames, which JVM created internally. It is worthwhile to note that the reflection frames that we captured in the previous example are still retained with SHOW_HIDDEN_FRAMES option. This is because SHOW_HIDDEN_FRAMES is a superset of SHOW_REFLECT_FRAMES.

3.5. Identifying the Calling Class

The option RETAIN_CLASS_REFERENCE retails the object of Class in all the StackFrames walked by the StackWalker. This allows us to call the methods StackWalker::getCallerClass and StackFrame::getDeclaringClass.

Let’s identify calling class using the StackWalker::getCallerClass method:

public void findCaller() {
    Class<?> caller = StackWalker
      .getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
      .getCallerClass();
    System.out.println(caller.getCanonicalName());
}

This time, we’ll call this method directly from a separate JUnit test:

@Test
public void giveStalkWalker_whenInvokingFindCaller_thenFindCallingClass() {
    new StackWalkerDemo().findCaller();
}

The output of caller.getCanonicalName(), will be:

com.baeldung.java9.stackwalker.StackWalkerDemoTest

Please note that the StackWalker::getCallerClass should not be called from the method at the bottom of the stack. as it will result in IllegalCallerException being thrown.

4. Conclusion

With this article, we’ve seen how easy it is to deal with StackFrames using the power of the StackWalker combined with the Stream API.

Of course, there are various other functionalities we can explore – such as skipping, dropping, and limiting the StackFrames. The official documentation contains a few solid examples for additional use cases.

And, as always, you can get the complete source code for this article over on GitHub.


Java Money and Currency API

$
0
0

1. Overview

JSR 354 – “Currency and Money” addresses the standardization of currencies and monetary amounts in Java.

Its goal is to add a flexible and extensible API to the Java ecosystem, and make working with monetary amounts simpler and safer.

The JSR did not make its way into JDK 9 but is a candidate for future JDK releases.

2. Setup

First, let’s define the dependency into our pom.xml file:

<dependency>
    <groupId>org.javamoney</groupId>
    <artifactId>moneta</artifactId>
    <version>1.1</version>
</dependency>

The latest version of the dependency can be checked here.

3. JSR-354 Features

The goals of “Currency and Money” API:

  • To provide an API for handling and calculating monetary amounts
  • To define classes representing currencies and monetary amounts, as well as monetary rounding
  • To deal with currency exchange rates
  • To deal with formatting and parsing of currencies and monetary amounts

4. Model

Main classes of the JSR-354 specification, are depicted in the following diagram:

The model holds two main interfaces CurrencyUnit and MonetaryAmount, explained in the following sections.

 5. CurrencyUnit

CurrencyUnit models the minimal properties of a currency. Its instances can be obtained using the Monetary.getCurrency method:

@Test
public void givenCurrencyCode_whenString_thanExist() {
    CurrencyUnit usd = Monetary.getCurrency("USD");

    assertNotNull(usd);
    assertEquals(usd.getCurrencyCode(), "USD");
    assertEquals(usd.getNumericCode(), 840);
    assertEquals(usd.getDefaultFractionDigits(), 2);
}

We create CurrencyUnit using a String representation of the currency, this could lead to a situation where we try to create a currency with nonexistent code. Creating currencies with nonexistent codes raise an UnknownCurrency exception:

@Test(expected = UnknownCurrencyException.class)
public void givenCurrencyCode_whenNoExist_thanThrowsError() {
    Monetary.getCurrency("AAA");
}

6. MonetaryAmount

MonetaryAmount is a numeric representation of a monetary amount. It’s always associated with CurrencyUnit and defines a monetary representation of a currency.

The amount can be implemented in different ways, focusing on the behavior of a monetary representation requirements, defined by each concrete use cases. For example. Money and FastMoney are implementations of the MonetaryAmount interface.

FastMoney implements MonetaryAmount using long as numeric representation, and is faster than BigDecimal at the cost of precision; it can be used when we need performance and precision isn’t an issue.

A generic instance can be created using a default factory. Let’s show the different way of obtaining MonetaryAmount instances:

@Test
public void givenAmounts_whenStringified_thanEquals() {
 
    CurrencyUnit usd = Monetary.getCurrency("USD");
    MonetaryAmount fstAmtUSD = Monetary.getDefaultAmountFactory()
      .setCurrency(usd).setNumber(200).create();
    Money moneyof = Money.of(12, usd);
    FastMoney fastmoneyof = FastMoney.of(2, usd);

    assertEquals("USD", usd.toString());
    assertEquals("USD 200", fstAmtUSD.toString());
    assertEquals("USD 12", moneyof.toString());
    assertEquals("USD 2.00000", fastmoneyof.toString());
}

7. Monetary Arithmetic

We can perform monetary arithmetic between Money and FastMoney but we need to be careful when we combine instances of these two classes.

For example when we compare one Euro instance of FastMoney with one Euro instance of Money the result is that they are not the same:

@Test
public void givenCurrencies_whenCompared_thanNotequal() {
    MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory()
      .setCurrency("USD").setNumber(1).create();
    Money oneEuro = Money.of(1, "EUR");

    assertFalse(oneEuro.equals(FastMoney.of(1, "EUR")));
    assertTrue(oneDolar.equals(Money.of(1, "USD")));
}

We can perform add, subtract, multiply, divide and other monetary arithmetic operations using the methods provided by the MonetaryAmount class.

Arithmetic operations should throw an ArithmeticException, if the arithmetic operations between amounts outperform the capabilities of the numeric representation type used, for example, if we try to divide one by three, we get an ArithmeticException because the result is an infinite number:

@Test(expected = ArithmeticException.class)
public void givenAmount_whenDivided_thanThrowsException() {
    MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory()
      .setCurrency("USD").setNumber(1).create();
    oneDolar.divide(3);
}

When adding or subtracting amounts, it’s better to use parameters which are instances of MonetaryAmount, as we need to ensure that both amounts have the same currency to perform operations between amounts.

7.1. Calculating Amounts

A total of amounts can be calculated in multiple ways, one way is simply to chain the amounts with:

@Test
public void givenAmounts_whenSummed_thanCorrect() {
    MonetaryAmount[] monetaryAmounts = new MonetaryAmount[] {
      Money.of(100, "CHF"), Money.of(10.20, "CHF"), Money.of(1.15, "CHF")};

    Money sumAmtCHF = Money.of(0, "CHF");
    for (MonetaryAmount monetaryAmount : monetaryAmounts) {
        sumAmtCHF = sumAmtCHF.add(monetaryAmount);
    }

    assertEquals("CHF 111.35", sumAmtCHF.toString());
}

Chaining can also be applied to subtracting:

Money calcAmtUSD = Money.of(1, "USD").subtract(fstAmtUSD);

Multiplying:

MonetaryAmount multiplyAmount = oneDolar.multiply(0.25);

Or dividing:

MonetaryAmount divideAmount = oneDolar.divide(0.25);

Let’s compare our arithmetic results using Strings, given that with Strings because the result also contains the currency:

@Test
public void givenArithmetic_whenStringified_thanEqualsAmount() {
    CurrencyUnit usd = Monetary.getCurrency("USD");

    Money moneyof = Money.of(12, usd);
    MonetaryAmount fstAmtUSD = Monetary.getDefaultAmountFactory()
      .setCurrency(usd).setNumber(200.50).create();
    MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory()
      .setCurrency("USD").setNumber(1).create();
    Money subtractedAmount = Money.of(1, "USD").subtract(fstAmtUSD);
    MonetaryAmount multiplyAmount = oneDolar.multiply(0.25);
    MonetaryAmount divideAmount = oneDolar.divide(0.25);

    assertEquals("USD", usd.toString());
    assertEquals("USD 1", oneDolar.toString());
    assertEquals("USD 200.5", fstAmtUSD.toString());
    assertEquals("USD 12", moneyof.toString());
    assertEquals("USD -199.5", subtractedAmount.toString());
    assertEquals("USD 0.25", multiplyAmount.toString());
    assertEquals("USD 4", divideAmount.toString());
}

8. Monetary Rounding

Monetary rounding is nothing else than a conversion from an amount with an undetermined precision to a rounded amount.

We’ll use the getDefaultRounding API provided by the Monetary class to make the conversion. The default rounding values are provided by the currency:

@Test
public void givenAmount_whenRounded_thanEquals() {
    MonetaryAmount fstAmtEUR = Monetary.getDefaultAmountFactory()
      .setCurrency("EUR").setNumber(1.30473908).create();
    MonetaryAmount roundEUR = fstAmtEUR.with(Monetary.getDefaultRounding());
    
    assertEquals("EUR 1.30473908", fstAmtEUR.toString());
    assertEquals("EUR 1.3", roundEUR.toString());
}

9. Currency Conversion

Currency conversion is an important aspect of dealing with money. Unfortunately, these conversions have a great variety of different implementations and use cases.

The API focuses on the common aspects of currency conversion based on the source, target currency, and exchange rate.

Currency conversion or the access of exchange rates can be parametrized:

@Test
public void givenAmount_whenConversion_thenNotNull() {
    MonetaryAmount oneDollar = Monetary.getDefaultAmountFactory().setCurrency("USD")
      .setNumber(1).create();

    CurrencyConversion conversionEUR = MonetaryConversions.getConversion("EUR");

    MonetaryAmount convertedAmountUSDtoEUR = oneDollar.with(conversionEUR);

    assertEquals("USD 1", oneDollar.toString());
    assertNotNull(convertedAmountUSDtoEUR);
}

A conversion is always bound to  currency. MonetaryAmount can simply be converted by passing a CurrencyConversion to the amount’s with method.

10. Currency Formatting

The formatting allows the access of formats based on java.util.Locale. Contrary to the JDK, the formatters defined by this API are thread-safe:

@Test
public void givenLocale_whenFormatted_thanEquals() {
    MonetaryAmount oneDollar = Monetary.getDefaultAmountFactory()
      .setCurrency("USD").setNumber(1).create();

    MonetaryAmountFormat formatUSD = MonetaryFormats.getAmountFormat(Locale.US);
    String usFormatted = formatUSD.format(oneDollar);

    assertEquals("USD 1", oneDollar.toString());
    assertNotNull(formatUSD);
    assertEquals("USD1.00", usFormatted);
}

Here we’re using the predefined format and creating a custom format for our currencies. The use of the standard format is straightforward using the method format of the MonetaryFormats class. We defined our custom format setting the pattern property of the format query builder.

As before because the currency is included in the result we test our results using Strings:

@Test
public void givenAmount_whenCustomFormat_thanEquals() {
    MonetaryAmount oneDollar = Monetary.getDefaultAmountFactory()
            .setCurrency("USD").setNumber(1).create();

    MonetaryAmountFormat customFormat = MonetaryFormats.getAmountFormat(AmountFormatQueryBuilder.
      of(Locale.US).set(CurrencyStyle.NAME).set("pattern", "00000.00 ¤").build());
    String customFormatted = customFormat.format(oneDollar);

    assertNotNull(customFormat);
    assertEquals("USD 1", oneDollar.toString());
    assertEquals("00001.00 US Dollar", customFormatted);
}

11. Summary

In this quick article, we’ve covered the basics of the Java Money & Currency JSR.

Monetary values are used everywhere, and Java provides is starting to support and handle monetary values, arithmetic or currency conversion.

As always, you can find the code from the article over on Github.

Concurrent Test Execution in Spring 5

$
0
0

1. Introduction

Starting with JUnit 4, tests can be run in parallel to gain speed for larger suites. The problem was concurrent test execution was not fully supported by the Spring TestContext Framework prior to Spring 5.

In this quick article, we’ll show how to use Spring 5 to run our tests in Spring projects concurrently.

2. Maven Setup

As a reminder, to run JUnit tests in parallel, we need to configure the maven-surefire-plugin to enable the feature:

<build>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.19.1</version>
        <configuration>
            <parallel>methods</parallel>
            <useUnlimitedThreads>true</useUnlimitedThreads>
        </configuration>
    </plugin>
</build>

You can check out the reference documentation for a more detailed configuration on parallel test execution.

3. Concurrent Test

The following example test would fail when running in parallel for versions prior to Spring 5.

However, it will run smoothly in Spring 5:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Spring5JUnit4ConcurrentTest.SimpleConfiguration.class)
public class Spring5JUnit4ConcurrentTest implements ApplicationContextAware, InitializingBean {

    @Configuration
    public static class SimpleConfiguration {}

    private ApplicationContext applicationContext;

    private boolean beanInitialized = false;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.beanInitialized = true;
    }

    @Override
    public void setApplicationContext(
      final ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Test
    public void whenTestStarted_thenContextSet() throws Exception {
        TimeUnit.SECONDS.sleep(2);
 
        assertNotNull(
          "The application context should have been set due to ApplicationContextAware semantics.",
          this.applicationContext);
    }

    @Test
    public void whenTestStarted_thenBeanInitialized() throws Exception {
        TimeUnit.SECONDS.sleep(2);
 
        assertTrue(
          "This test bean should have been initialized due to InitializingBean semantics.",
          this.beanInitialized);
    }
}

When running sequentially, the tests above would take around 6 seconds to pass. With concurrent execution, it will only take about 4.5 seconds – which is quite typical for how much time we can expect to save in larger suites as well.

4. Under the Hood

The primary reason prior versions of the framework didn’t support running tests concurrently was due to the management of TestContext by the TestContextManager.

In Spring 5, the TestContextManager uses a thread local – TestContext – to ensure that operations on TestContexts in each thread would not interfere with each other. Thus thread-safety is guaranteed for most method level and class level concurrent tests:

public class TestContextManager {

    // ...
    private final TestContext testContext;

    private final ThreadLocal<TestContext> testContextHolder = new ThreadLocal<TestContext>() {
        protected TestContext initialValue() {
            return copyTestContext(TestContextManager.this.testContext);
        }
    };

    public final TestContext getTestContext() {
        return this.testContextHolder.get();
    }

    // ...
}

Note that the concurrency support does not apply to all kinds of tests; we need to exclude tests that:

  • change external shared states, such as states in caches, databases, message queues, etc.
  • require specific execution orders, for example, tests that use JUnit‘s @FixMethodOrder
  • modify the ApplicationContext, which are generally marked by @DirtiesContext

5. Summary

In this quick tutorial, we’ve shown an basic example using Spring 5 to run tests in parallel.

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

A Guide to the Axon Framework

$
0
0

1. Overview

In this article, we’ll be looking at the Axon framework and how it helps us implement an architecture based on CQRS (Command Query Responsibility Segregation) and potentially Event Sourcing.

Note that a lot of these concepts come right out of DDD, which is beyond the scope of this current article.

2. Maven Dependencies

Before we start creating out sample application, we need to add the axon-core and axon-test dependencies into our pom.xml:

<dependency>
    <groupId>org.axonframework</groupId>
    <artifactId>axon-core</artifactId>
    <version>${axon.version}</version>
</dependency>
<dependency>
    <groupId>org.axonframework</groupId>
    <artifactId>axon-test</artifactId>
    <version>${axon.version}</version>
    <scope>test<scope>
</dependency>

<properties>
    <axon.version>3.0.2</axon.version>
</properties>

3. Message Service – Commands 

With the initial goal of doing CQRS in out system, we’ll define two types of actions that the user can perform:

  1.  create a new text message
  2.  mark text message as read

Naturally these will be two commands that model our domain – CreateMessageCommand and MarkReadMessageCommand:

public class CreateMessageCommand {
 
    @TargetAggregateIdentifier
    private String id;
    private String text;
 
    public CreateMessageCommand(String id, String text) {
        this.id = id;
        this.text = text;
    }
 
    // ...
}
public class MarkReadMessageCommand {
 
    @TargetAggregateIdentifier
    private String id;
 
    public MarkReadMessageCommand(String id) {
        this.id = id;
    }
    
    // ...
}

The TargetAggregateIdentifier annotation tells Axon that the annotated field is an id of the given aggregate. We’ll briefly touch on aggregates soon.

4. Events

Our aggregate will be reacting to the above-created commands by producing MessageCreatedEvent and MessageReadEvent events:

public class MessageCreatedEvent {
 
    private String id;
    private String text;
 
    // standard constructors, getters, setters 
}
 
public class MessageReadEvent {
 
    private String id;
 
    // standard constructors, getters, setters
}

5. Aggregates – Producing Events on Commands

Now that we’ve modeled our commands, we need to create handlers that will produce events for commands.

Let’s create an aggregate class:

public class MessagesAggregate {

    @AggregateIdentifier
    private String id;

    @CommandHandler
    public MessagesAggregate(CreateMessageCommand command) {
        apply(new MessageCreatedEvent(command.getId(), command.getText()));
    }

    @EventHandler
    public void on(MessageCreatedEvent event) {
        this.id = event.getId();
    }

    @CommandHandler
    public void markRead(MarkReadMessageCommand command) {
        apply(new MessageReadEvent(id));
    }
    
    // standard constructors
}

Each aggregate needs to have an id field, and we specify this by using an AggregateIdentifier annotation.

Our aggregate is created when CreateMessageCommand arrives – receiving that command will produce a MessageCreatedEvent.

At this point, the aggregate is in the messageCreated state. When the MarkReadMessageCommand arrives, the aggregate is producing a MessageReadEvent.

6. Testing our Setup

Firstly, we need to set up our test by creating a FixtureConfiguration for the MessagesAggregate:

private FixtureConfiguration<MessagesAggregate> fixture;

@Before
public void setUp() throws Exception {
    fixture = 
      new AggregateTestFixture<MessagesAggregate>(MessagesAggregate.class);
}

The first test case should cover the simplest situation – when the CreateMessageCommand arrives in our aggregate, it should produce the MessageCreatedEvent:

String eventText = "Hello, how is your day?";
String id = UUID.randomUUID().toString();
fixture.given()
  .when(new CreateMessageCommand(id, eventText))
  .expectEvents(new MessageCreatedEvent(id, eventText));

Next, we will test a situation when aggregate already produced MessageCreatedEvent and the MarkReadMessageCommand arrives. It should produce a MessageReadEvent:

String id = UUID.randomUUID().toString();

fixture.given(new MessageCreatedEvent(id, "Hello"))
  .when(new MarkReadMessageCommand(id))
  .expectEvents(new MessageReadEvent(id));

7. Putting Everything Together

We created commands, events, and aggregates. To start our application we need to glue everything together.

First, we need to create a command bus to which commands will be sent:

CommandBus commandBus = new SimpleCommandBus();
CommandGateway commandGateway = new DefaultCommandGateway(commandBus);

Next, we need to setup a message bus to which produced events will be sent:

EventStore eventStore = new EmbeddedEventStore(new InMemoryEventStorageEngine());

EventSourcingRepository<MessagesAggregate> repository
  = new EventSourcingRepository<>(MessagesAggregate.class, eventStore);

Events should be persistent, so we need to define a repository for storing them.

In this simple example, we’re storing events in memory. In a production system, it should of course be a database or some other type of persistence store.

If we’re doing Event Sourcing, the EventStore is the central component of the architecture. All events produced by the aggregate need to be persisted into to store to keep a master record of all change in the system.

Events are immutable, so once they are saved in the event store, they can not be modified or deleted. Using events we can recreate a state of a system to any point in the time, taking all events that were produced to this specific point in time.

Before starting the application we need to set up the aggregate that will be handling commands and producing events:

AggregateAnnotationCommandHandler<MessagesAggregate> handler = 
  new AggregateAnnotationCommandHandler<MessagesAggregate>(
    MessagesAggregate.class, repository);
handler.subscribe(commandBus);

The last thing we should declare is a handler that will subscribe to the events produced by the aggregate.

We’ll create a message event handler that will handle both messages – the MessageCreatedEvent and the MessageReadEvent:

public class MessagesEventHandler {

    @EventHandler
    public void handle(MessageCreatedEvent event) {
        System.out.println("Message received: " + event.getText() + " (" + event.getId() + ")");
    }

    @EventHandler
    public void handle(MessageReadEvent event) {
        System.out.println("Message read: " + event.getId());
    }
}

We need to define that this listener should handle events by invoking a subscribe() method:

AnnotationEventListenerAdapter annotationEventListenerAdapter
  = new AnnotationEventListenerAdapter(new MessagesEventHandler());
eventStore.subscribe(eventMessages -> eventMessages.forEach(e -> {
    try {
        annotationEventListenerAdapter.handle(e);
    } catch (Exception e1) {
        throw new RuntimeException(e1);
    }
}));

We completed the setup, so now we can send some commands to the commandGateway:

String itemId = UUID.randomUUID().toString();
commandGateway.send(new CreateMessageCommand(itemId, "Hello, how is your day?"));
commandGateway.send(new MarkReadMessageCommand(itemId));

After running our application, the MessagesEventHandler should handle events produced by the MessagesAggregate class, and we should see similar output:

Message received: Hello, how is your day? (d2ba9cbe-1a44-428e-a710-13b1bdc67c4b)
Message read: d2ba9cbe-1a44-428e-a710-13b1bdc67c4b

8. Conclusion

In this article we introduced the Axon framework as a powerful base to building a CQRS and Event Sourcing system architecture.

We implemented a simple message application using the framework – to show how that should be structured in practice.

The implementation of all these examples and code snippets can be found over on GitHub; this is a Maven project, so it should be easy to import and run as it is.

Spring Security and OpenID Connect

$
0
0

1. Overview

In this quick tutorial, we’ll focus on setting up OpenID Connect with a Spring Security OAuth2 implementation.

OpenID Connect is a simple identity layer built on top of the OAuth 2.0 protocol.

And, more specifically, we’ll learn how to authenticate users using the OpenID Connect implementation from Google.

2. Maven Configuration

First, we need to add the following dependencies to our Spring Boot application:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
</dependency>

3. The Id Token

Before we dive into the implementation details, let’s have a quick look at how OpenID works, and how we’ll interact with it.

At this point, it’s of course important to already have an understanding of OAuth2, since OpenID is built on top of OAuth.

First, in order to use the identity functionality, we’ll make use of a new OAuth2 scope called openid. This will result in an extra field in our Access Token – “id_token“.

The id_token is a JWT (JSON Web Token) that contains identity information about the user, signed by identity provider (in our case Google).

Finally, both server(Authorization Code) and implicit flows are the most commonly used ways of obtaining id_token, in our example we will use server flow.

3. OAuth2 Client Configuration

Next, let’s configure our OAuth2 client – as follows:

@Configuration
@EnableOAuth2Client
public class GoogleOpenIdConnectConfig {
    @Value("${google.clientId}")
    private String clientId;

    @Value("${google.clientSecret}")
    private String clientSecret;

    @Value("${google.accessTokenUri}")
    private String accessTokenUri;

    @Value("${google.userAuthorizationUri}")
    private String userAuthorizationUri;

    @Value("${google.redirectUri}")
    private String redirectUri;

    @Bean
    public OAuth2ProtectedResourceDetails googleOpenId() {
        AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
        details.setClientId(clientId);
        details.setClientSecret(clientSecret);
        details.setAccessTokenUri(accessTokenUri);
        details.setUserAuthorizationUri(userAuthorizationUri);
        details.setScope(Arrays.asList("openid", "email"));
        details.setPreEstablishedRedirectUri(redirectUri);
        details.setUseCurrentUri(false);
        return details;
    }

    @Bean
    public OAuth2RestTemplate googleOpenIdTemplate(OAuth2ClientContext clientContext) {
        return new OAuth2RestTemplate(googleOpenId(), clientContext);
    }
}

And here is application.properties:

google.clientId=<your app clientId>
google.clientSecret=<your app clientSecret>
google.accessTokenUri=https://www.googleapis.com/oauth2/v3/token
google.userAuthorizationUri=https://accounts.google.com/o/oauth2/auth
google.redirectUri=http://localhost:8081/google-login

Note that:

  • You first need to obtain OAuth 2.0 credentials for your Google web app from Google Developers Console.
  • We used scope openid to obtain id_token.
  • we also used an extra scope email to include user email in id_token identity information.
  • The redirect URI http://localhost:8081/google-login is the same one used in our Google web app.

4. Custom OpenID Connect Filter

Now, we need to create our own custom OpenIdConnectFilter to extract authentication from id_token – as follows:

public class OpenIdConnectFilter extends AbstractAuthenticationProcessingFilter {
    @Override
    public Authentication attemptAuthentication(
      HttpServletRequest request, HttpServletResponse response) 
      throws AuthenticationException, IOException, ServletException {
        OAuth2AccessToken accessToken;
        try {
            accessToken = restTemplate.getAccessToken();
        } catch (OAuth2Exception e) {
            throw new BadCredentialsException("Could not obtain access token", e);
        }
        try {
            String idToken = accessToken.getAdditionalInformation().get("id_token").toString();
            Jwt tokenDecoded = JwtHelper.decode(idToken);
            Map<String, String> authInfo = new ObjectMapper().readValue(tokenDecoded.getClaims(), Map.class);

            OpenIdConnectUserDetails user = new OpenIdConnectUserDetails(authInfo, accessToken);
            return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        } catch (InvalidTokenException e) {
            throw new BadCredentialsException("Could not obtain user details from token", e);
        }
    }
}

And here is our simple OpenIdConnectUserDetails:

public class OpenIdConnectUserDetails implements UserDetails {
    private String userId;
    private String username;
    private OAuth2AccessToken token;

    public OpenIdConnectUserDetails(Map<String, String> userInfo, OAuth2AccessToken token) {
        this.userId = userInfo.get("sub");
        this.username = userInfo.get("email");
        this.token = token;
    }
}

Note that:

  • Spring Security JwtHelper to decode id_token.
  • id_token always contains “sub” field which is a unique identifier for the user.
  • id_token will also contain “email” field as we added email scope to our request.

5. Security Configuration

Next, let’s discuss our security configuration:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private OAuth2RestTemplate restTemplate;

    @Bean
    public OpenIdConnectFilter openIdConnectFilter() {
        OpenIdConnectFilter filter = new OpenIdConnectFilter("/google-login");
        filter.setRestTemplate(restTemplate);
        return filter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .addFilterAfter(new OAuth2ClientContextFilter(), 
          AbstractPreAuthenticatedProcessingFilter.class)
        .addFilterAfter(OpenIdConnectFilter(), 
          OAuth2ClientContextFilter.class)
        .httpBasic()
        .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/google-login"))
        .and()
        .authorizeRequests()
        .anyRequest().authenticated();
    }
}

Note that:

  • We added our custom OpenIdConnectFilter after OAuth2ClientContextFilter
  • We used a simple security configuration to redirect users to “/google-login” to get authenticated by Google

6. User Controller

Next, here is a simple controller to test our app:

@Controller
public class HomeController {
    @RequestMapping("/")
    @ResponseBody
    public String home() {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        return "Welcome, " + username;
    }
}

Sample response (after redirect to Google to approve app authorities) :

Welcome, example@gmail.com

7. Sample OpenID Connect Process

Finally, let’s take a look at a sample OpenID Connect authentication process.

First, we’re going to send an Authentication Request:

https://accounts.google.com/o/oauth2/auth?
    client_id=sampleClientID
    response_type=code&
    scope=openid%20email&
    redirect_uri=http://localhost:8081/google-login&
    state=abc

The response (after user approval) is a redirect to:

http://localhost:8081/google-login?state=abc&code=xyz

Next, we’re going to exchange the code for an Access Token and id_token:

POST https://www.googleapis.com/oauth2/v3/token 
    code=xyz&
    client_id= sampleClientID&
    client_secret= sampleClientSecret&
    redirect_uri=http://localhost:8081/google-login&
    grant_type=authorization_code

Here’s a sample Response:

{
    "access_token": "SampleAccessToken",
    "id_token": "SampleIdToken",
    "token_type": "bearer",
    "expires_in": 3600,
    "refresh_token": "SampleRefreshToken"
}

Finally, here’s what the information of the actual id_token looks like:

{
    "iss":"accounts.google.com",
    "at_hash":"AccessTokenHash",
    "sub":"12345678",
    "email_verified":true,
    "email":"example@gmail.com",
     ...
}

So you can immediately see just how useful the user information inside the token is for providing identity information to our own application.

8. Conclusion

In this quick intro tutorial, we learned how to authenticate users using the OpenID Connect implementation from Google.

And, as always, you can find the source code over on GitHub.

Ant Colony Optimization

$
0
0

1. Introduction

The aim of this series is to explain the idea of genetic algorithms and show the most known implementations.

In this tutorial, we’ll describe the concept of the ant colony optimization (ACO), followed by the code example.

2. How ACO Works

ACO is a genetic algorithm inspired by an ant’s natural behavior. To fully understand the ACO algorithm, we need to get familiar with its basic concepts:

  • ants use pheromones to find the shortest path between home and food source
  • pheromones evaporate quickly
  • ants prefer to use shorter paths with denser pheromone

Let’s show a simple example of ACO used in the Traveling Salesman Problem. In the following case, we need to find the shortest path between all nodes in the graph:

 

Following by natural behaviors, ants will start to explore new paths during the exploration. Stronger blue color indicates the paths that are used more often than the others, whereas green color indicates the current shortest path that is found:

 

As a result, we’ll achieve the shortest path between all nodes:

 

The nice GUI-based tool for ACO testing can be found here.

3. Java Implementation

3.1. ACO Parameters

Let’s discuss the main parameters for the ACO algorithm, declared in the AntColonyOptimization class:

private double c = 1.0;
private double alpha = 1;
private double beta = 5;
private double evaporation = 0.5;
private double Q = 500;
private double antFactor = 0.8;
private double randomFactor = 0.01;

Parameter c indicates the original number of trails, at the start of the simulation. Furthermore, alpha controls the pheromone importance, while beta controls the distance priority. In general, the beta parameter should be greater than alpha for the best results.

Next, the evaporation variable shows the percent how much the pheromone is evaporating in every iteration, whereas provides information about the total amount of pheromone left on the trail by each Ant, and antFactor tells us how many ants we’ll use per city.

Finally, we need to have a little bit of randomness in our simulations, and this is covered by randomFactor.

3.2. Create Ants

Each Ant will be able to visit a specific city, remember all visited cities, and keep track of the trail length:

public void visitCity(int currentIndex, int city) {
    trail[currentIndex + 1] = city;
    visited[city] = true;
}

public boolean visited(int i) {
    return visited[i];
}

public double trailLength(double graph[][]) {
    double length = graph[trail[trailSize - 1]][trail[0]];
    for (int i = 0; i < trailSize - 1; i++) {
        length += graph[trail[i]][trail[i + 1]];
    }
    return length;
}

3.3. Setup Ants

At the very beginning, we need to initialize our ACO code implementation by providing trails and ants matrices:

graph = generateRandomMatrix(noOfCities);
numberOfCities = graph.length;
numberOfAnts = (int) (numberOfCities * antFactor);

trails = new double[numberOfCities][numberOfCities];
probabilities = new double[numberOfCities];
ants = new Ant[numberOfAnts];
IntStream.range(0, numberOfAnts).forEach(i -> ants.add(new Ant(numberOfCities)));

Next, we need to setup the ants matrix to start with a random city:

public void setupAnts() {
    IntStream.range(0, numberOfAnts)
      .forEach(i -> {
          ants.forEach(ant -> {
              ant.clear();
              ant.visitCity(-1, random.nextInt(numberOfCities));
          });
      });
    currentIndex = 0;
}

For each iteration of the loop, we’ll perform the following operations:

IntStream.range(0, maxIterations).forEach(i -> {
    moveAnts();
    updateTrails();
    updateBest();
});

3.4. Move Ants

Let’s start with the moveAnts() method. We need to choose the next city for all ants, remembering that each ant tries to follow other ants’ trails:

public void moveAnts() {
    IntStream.range(currentIndex, numberOfCities - 1).forEach(i -> {
        ants.forEach(ant -> {
            ant.visitCity(currentIndex, selectNextCity(ant));
        });
        currentIndex++;
    });
}

The most important part is to properly select next city to visit. We should select the next town based on the probability logic. First, we can check if Ant should visit a random city:

int t = random.nextInt(numberOfCities - currentIndex);
if (random.nextDouble() < randomFactor) {
    OptionalInt cityIndex = IntStream.range(0, numberOfCities)
      .filter(i -> i == t && !ant.visited(i))
      .findFirst();
    if (cityIndex.isPresent()) {
        return cityIndex.getAsInt();
    }
}

If we didn’t select any random city, we need to calculate probabilities to select the next city, remembering that ants prefer to follow stronger and shorter trails. We can do this by storing the probability of moving to each city in the array:

public void calculateProbabilities(Ant ant) {
    int i = ant.trail[currentIndex];
    double pheromone = 0.0;
    for (int l = 0; l < numberOfCities; l++) {
        if (!ant.visited(l)){
            pheromone
              += Math.pow(trails[i][l], alpha) * Math.pow(1.0 / graph[i][l], beta);
        }
    }
    for (int j = 0; j < numberOfCities; j++) {
        if (ant.visited(j)) {
            probabilities[j] = 0.0;
        } else {
            double numerator
              = Math.pow(trails[i][j], alpha) * Math.pow(1.0 / graph[i][j], beta);
            probabilities[j] = numerator / pheromone;
        }
    }
}

After we calculate probabilities, we can decide to which city to go to by using:

double r = random.nextDouble();
double total = 0;
for (int i = 0; i < numberOfCities; i++) {
    total += probabilities[i];
    if (total >= r) {
        return i;
    }
}

3.5. Update Trails

In this step, we should update trails and the left pheromone:

public void updateTrails() {
    for (int i = 0; i < numberOfCities; i++) {
        for (int j = 0; j < numberOfCities; j++) {
            trails[i][j] *= evaporation;
        }
    }
    for (Ant a : ants) {
        double contribution = Q / a.trailLength(graph);
        for (int i = 0; i < numberOfCities - 1; i++) {
            trails[a.trail[i]][a.trail[i + 1]] += contribution;
        }
        trails[a.trail[numberOfCities - 1]][a.trail[0]] += contribution;
    }
}

3.6. Update the Best Solution

This is the last step of each iteration. We need to update the best solution in order to keep the reference to it:

private void updateBest() {
    if (bestTourOrder == null) {
        bestTourOrder = ants[0].trail;
        bestTourLength = ants[0].trailLength(graph);
    }
    for (Ant a : ants) {
        if (a.trailLength(graph) < bestTourLength) {
            bestTourLength = a.trailLength(graph);
            bestTourOrder = a.trail.clone();
        }
    }
}

After all iterations, the final result will indicate the best path found by ACO. Please note that by increasing the number of cities, the probability of finding the shortest path decreases. 

4. Conclusion

This tutorial introduces the Ant Colony Optimization algorithm. You can learn about genetic algorithms without any previous knowledge of this area, having only basic computer programming skills.

The complete source code for the code snippets in this tutorial is available in the GitHub project.

For all articles in the series, including other examples of genetic algorithms, check out the following links:

Introduction to Twitter4J

$
0
0

1. Overview

In this article, we will have a look at using Twitter4J in a Java application to communicate with Twitter.

2. Twitter4J

Twitter4J is an open source Java library, which provides a convenient API for accessing the Twitter API.

Simply put, here’s how we can interact with the Twitter API; we can:

  • Post a tweet
  • Get timeline of a user, with a list of latest tweets
  • Send and receive direct messages
  • Search for tweets and much more

This library ensures that that we can easily do these operations, and it also ensures the security and privacy of a user – for which we naturally need to have OAuth credentials configured in our app.

3. Maven Dependencies

We need to start by defining the dependency for Twitter4J in our pom.xml:

<dependency>
    <groupId>org.twitter4j</groupId>
    <artifactId>twitter4j-stream</artifactId>
    <version>4.0.6</version>
</dependency>

To check if any new version of the library has been released – track the releases here.

4. Configuration

Configuring Twitter4J is easy and can be done in various ways – for example in a plain text file or a Java class or even using environment variables.

Let’s look at each of these ways, one at a time.

4.1. Plain Text File

We can use a plain text file – named twitter4j.properties – to hold our configuration details. Let’s look at the properties which need to be provided:

oauth.consumerKey =       // your key
oauth.consumerSecret =    // your secret
oauth.accessToken =       // your token
oauth.accessTokenSecret = // your token secret

All these attributes can be obtained from Twitter Developer console after you make a new app.

4.2. Java Class

We can also use a ConfigurationBuilder class to configure Twitter4J programmatically in Java:

ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
  .setOAuthConsumerKey("your consumer key")
  .setOAuthConsumerSecret("your consumer secret")
  .setOAuthAccessToken("your access token")
  .setOAuthAccessTokenSecret("your access token secret");
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();

Note that we’ll be using the Twitter instance in next section – when we start to fetch data.

4.3. Environment Variables

Configuring through environment variables is another choice we have. If we do that, note that we’ll need a twitter4j prefix in our variables:

$ export twitter4j.oauth.consumerKey =       // your key
$ export twitter4j.oauth.consumerSecret =    // your secret
$ export twitter4j.oauth.accessToken =       // your access token
$ export twitter4j.oauth.accessTokenSecret = // your access token secret

5. Adding / Retrieving Real-Time Tweet Data

With a fully configured application, we can finally interact with Twitter.

Let’s look at few examples.

5.1. Post A Tweet

We’ll start by updating a tweet on Twitter:

public String createTweet(String tweet) throws TwitterException {
    Twitter twitter = getTwitterinstance();
    Status status = twitter.updateStatus("creating baeldung API");
    return status.getText();
}

By using status.getText(), we can retrieve the tweet just posted.

5.2. Get the Timeline

We can also fetch a list of tweets from the user’s timeline:

public List<String> getTimeLine() throws TwitterException {
    Twitter twitter = getTwitterinstance();
    
    return twitter.getHomeTimeline().stream()
      .map(item -> item.getText())
      .collect(Collectors.toList());
}

By using twitter.getHomeTimeline(), we get all tweets posted by the current account ID.

5.3. Send a Direct Message

Sending and receiving a direct message to followers is also possible using the Twitter4j:

public static String sendDirectMessage(String recipientName, String msg) 
  throws TwitterException {
 
    Twitter twitter = getTwitterinstance();
    DirectMessage message = twitter.sendDirectMessage(recipientName, msg);
    return message.getText();
}

The sendDirectMessage method takes two parameters:

  • RecipientName: the twitter username of a message recipient
  • msg: message content

If recipient will not be found, the sendDirectMessage will throw an exception with exception code 150.

5.4. Search for Tweets

We can also search for tweets containing some text. By doing this, we’ll get a list of tweets with the username of users.

Let’s see how such a search can be performed:

public static List<String> searchtweets() throws TwitterException {
 
    Twitter twitter = getTwitterinstance();
    Query query = new Query("source:twitter4j baeldung");
    QueryResult result = twitter.search(query);
    
    return result.getTweets().stream()
      .map(item -> item.getText())
      .collect(Collectors.toList());
}

Clearly, we can iterate over each tweet received in a QueryResult and fetch relative data.

5.5. The Streaming API

Twitter Streaming API is useful when updates are required in real-time; it handles thread creation and listens to events.

Let’s create a listener which listens to tweet updates from a user:

public static void streamFeed() {

    StatusListener listener = new StatusListener() {

        @Override
        public void onException(Exception e) {
            e.printStackTrace();
        }
        @Override
        public void onDeletionNotice(StatusDeletionNotice arg) {
        }
        @Override
        public void onScrubGeo(long userId, long upToStatusId) {
        }
        @Override
        public void onStallWarning(StallWarning warning) {
        }
        @Override
        public void onStatus(Status status) {
        }
        @Override
        public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
        }
    };

    TwitterStream twitterStream = new TwitterStreamFactory().getInstance();

    twitterStream.addListener(listener);

    twitterStream.sample();
}

We can put some println() statement to check the output tweet stream in all of the methods. All tweets have location metadata associated with it.

Please note that all the tweets data fetched by the API are in the UTF-8 format and since Twitter is a multi-language platform, some data format may be unrecognizable based upon its origin.

6. Conclusion

This article was a quick but comprehensive introduction to using Twitter4J with Java.

The implementation of shown examples can be found on GitHub  – this is a Maven based project, so it should be easy to import and run as it is. The only change we need to do is to insert our own OAuth credentials.

Guide to @Immutable Annotation in Hibernate

$
0
0

1. Overview

In this article, we’ll talk about how we can make an entity, collection or attribute Immutable in Hibernate.

By default, fields are mutable, which means we’re able to perform operations on them that change their state.

2. Maven

To get our project up and running, we first need to add the necessary dependencies into our pom.xml. And as we’re working with Hibernate, we are going to add the corresponding dependency:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.2.8.Final</version>
</dependency>

And, because we are working with HSQLDB, we also need:

<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.3.4</version>
</dependency>

3. Annotation on Entities

First, let’s define a simple entity class:

@Entity
@Immutable
@Table(name = "events")
public class Event {
 
    @Id
    @Column(name = "event_id")
    @GeneratedValue(generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    private Long id;

    @Column(name = "title")
    private String title;

    // standard setters and getters
}

As you have noticed we have added already the @Immutable annotation to our entity, so if we try and save an Event:

@Test
public void addEvent() {
    Event event = new Event();
    event.setTitle("My Event");
    event.setGuestList(Sets.newHashSet("guest"));
    session.save(event);
    session.getTransaction().commit();
}

Then we should get the output:

Hibernate: insert into events (title, event_id) values (?, ?)

The output should be the same even if we remove the annotation, meaning there’s no effect when we try to add an entity regardless of the annotation.

3.1. Updating the Entity

Now, we had no issue saving an entity, let’s try to update it:

@Test
public void updateEvent() {
    Event event = (Event) session.createQuery(
      "FROM Event WHERE title='My Event'").list().get(0);
    event.setTitle("Public Event");
    session.saveOrUpdate(event);
    session.getTransaction().commit();
}

Hibernate will simply ignore the update operation without throwing an exception. However, if we remove the @Immutable annotation we get a different result:

Hibernate: select ... from events where title='My Event'
Hibernate: update events set title=? where event_id=?

What this tells us is that our object is now mutable (mutable is the default value if we don’t include the annotation) and will allow the update to do its job.

3.2. Deleting an Entity

When it comes to deleting an entity:

@Test
public void deleteEvent() {
    Event event = (Event) session.createQuery(
      "FROM Event WHERE title='My Event'").list().get(0);
    session.delete(event);
    session.getTransaction().commit();
}

We’ll be able to perform the delete regardless if it is mutable or not:

Hibernate: select ... from events where title='My Event'
Hibernate: delete from events where event_id=?

4. Annotation on Collections

So far we’ve seen what the annotation does to entities, but as we mentioned in the beginning, it can also be applied to collections.

First, let’s add a collection to our Event class:

@Immutable
public Set<String> getGuestList() {
    return guestList;
}

Same as before, we’ve added the annotation beforehand, so if we go ahead and try to add an element to our collection:

org.hibernate.HibernateException: 
  changed an immutable collection instance: [com.baeldung.entities.Event.guestList#1]

This time we get an exception because with collections we are not allowed to add nor delete them.

4.1. Deleting Collections

The other scenario where a Collection by being immutable will throw an exception it’s whenever we try to delete and we have set the @Cascade annotation.

So, whenever @Immutable is present and we attempt to delete:

@Test
public void deleteCascade() {
    Event event = (Event) session.createQuery(
      "FROM Event WHERE title='Public Event'").list().get(0);
    String guest = event.getGuestList().iterator().next();
    event.getGuestList().remove(guest);
    session.saveOrUpdate(event);
    session.getTransaction().commit();
}

Output:

org.hibernate.HibernateException: 
  changed an immutable collection instance:
  [com.baeldung.entities.Event.guestList#1]

5. XML Notes

Finally, the configuration can also be done using XML through the mutable=false attribute:

<hibernate-mapping>
    <class name="com.baeldung.entities.Event" mutable="false">
        <id name="id" column="event_id">
            <generator class="increment"/>
        </id>
        <property name="title"/>
    </class>
</hibernate-mapping>

However, since we basically implemented the examples using the annotation method, we will not get into details using XML.

6. Conclusion

In this quick article we explore the useful @Immutable annotation out of Hibernate, and how that can help us define better semantics and constraints on our data.

As always, the implementation of all of these examples and snippets can be found in the GitHub project. This is a Maven-based project so it should be easy to import and run.


Spring LDAP Overview

$
0
0

1. Overview

LDAP directory servers are read-optimized hierarchical data stores. Typically, they’re used for storing user-related information required for user authentication and authorization.

In this article, we’ll explore the Spring LDAP APIs to authenticate and search for users, as well as to create and modify users in the directory server. The same set of APIs can be used for managing any other type of entries in LDAP.

2. Maven Dependencies

Let’s begin by adding the required Maven dependency:

<dependency>
    <groupId>org.springframework.ldap</groupId>
    <artifactId>spring-ldap-core</artifactId>
    <version>2.3.1.RELEASE</version>
</dependency>

The latest version of this dependency can be found at spring-ldap-core.

3. Data Preparation

For the purpose of this article, let’s first create the following LDAP entry:

ou=users,dc=example,dc=com (objectClass=organizationalUnit)

Under this node, we will create new users, modify existing users, authenticate existing users and search for information.

4. Spring LDAP APIs

4.1. ContextSource & LdapTemplate Bean Definition

ContextSource is used for creating the LdapTemplate. We will see the use of ContextSource during user authentication in the next section:

@Bean
public LdapContextSource contextSource() {
    LdapContextSource contextSource = new LdapContextSource();
    
    contextSource.setUrl(env.getRequiredProperty("ldap.url"));
    contextSource.setBase(
      env.getRequiredProperty("ldap.partitionSuffix"));
    contextSource.setUserDn(
      env.getRequiredProperty("ldap.principal"));
    contextSource.setPassword(
      env.getRequiredProperty("ldap.password"));
    
    return contextSource;
}

LdapTemplate is used for creation and modification of LDAP entries:

@Bean
public LdapTemplate ldapTemplate() {
    return new LdapTemplate(contextSource());
}

4.2. User Authentication

Let’s now implement a simple piece of logic to authenticate an existing user:

public void authenticate(String username, String password) {
    contextSource
      .getContext(
        "cn=" + 
         username + 
         ",ou=users," + 
         env.getRequiredProperty("ldap.partitionSuffix"), password);
}

4.3. User Creation

Next, let’s create a new user and store an SHA hash of the password in LDAP.

At the time of authentication, the LDAP server generates the SHA hash of the supplied password and compares it to the stored one:

public void create(String username, String password) {
    Name dn = LdapNameBuilder
      .newInstance()
      .add("ou", "users")
      .add("cn", username)
      .build();
    DirContextAdapter context = new DirContextAdapter(dn);

    context.setAttributeValues(
      "objectclass", 
      new String[] 
        { "top", 
          "person", 
          "organizationalPerson", 
          "inetOrgPerson" });
    context.setAttributeValue("cn", username);
    context.setAttributeValue("sn", username);
    context.setAttributeValue
      ("userPassword", digestSHA(password));

    ldapTemplate.bind(context);
}

digestSHA() is a custom method which returns the Base64 encoded string of the SHA hash of the supplied password.

Finally, the bind() method of LdapTemplate is used to create an entry in the LDAP server.

4.4. User Modification

We can modify an existing user or entry with the following method:

public void modify(String username, String password) {
    Name dn = LdapNameBuilder.newInstance()
      .add("ou", "users")
      .add("cn", username)
      .build();
    DirContextOperations context 
      = ldapTemplate.lookupContext(dn);

    context.setAttributeValues
      ("objectclass", 
          new String[] 
            { "top", 
              "person", 
              "organizationalPerson", 
              "inetOrgPerson" });
    context.setAttributeValue("cn", username);
    context.setAttributeValue("sn", username);
    context.setAttributeValue("userPassword", 
      digestSHA(password));

    ldapTemplate.modifyAttributes(context);
}

The lookupContext() method is used to find the supplied user.

4.5. User Search

We can search for existing users using search filters:

public List<String> search(String username) {
    return ldapTemplate
      .search(
        "ou=users", 
        "cn=" + username, 
        (AttributesMapper<String>) attrs -> (String) attrs.get("cn").get());
}

The AttributesMapper is used to get the desired attribute value from the entries found. Internally, Spring LdapTemplate invokes the AttributesMapper for all the entries found and creates a list of the attribute values.

5. Testing

spring-ldap-test provides an embedded LDAP server based on ApacheDS 1.5.5. To setup the embedded LDAP server for testing, we need to configure the following Spring bean:

@Bean
public TestContextSourceFactoryBean testContextSource() {
    TestContextSourceFactoryBean contextSource 
      = new TestContextSourceFactoryBean();
    
    contextSource.setDefaultPartitionName(
      env.getRequiredProperty("ldap.partition"));
    contextSource.setDefaultPartitionSuffix(
      env.getRequiredProperty("ldap.partitionSuffix"));
    contextSource.setPrincipal(
      env.getRequiredProperty("ldap.principal"));
    contextSource.setPassword(
      env.getRequiredProperty("ldap.password"));
    contextSource.setLdifFile(
      resourceLoader.getResource(
        env.getRequiredProperty("ldap.ldiffile")));
    contextSource.setPort(
      Integer.valueOf(
        env.getRequiredProperty("ldap.port")));
    return contextSource;
}

Let’s test our user search method with JUnit:

@Test
public void 
  givenLdapClient_whenCorrectSearchFilter_thenEntriesReturned() {
    List<String> users = ldapClient
      .search(SEARCH_STRING);
 
    assertThat(users, Matchers.containsInAnyOrder(USER2, USER3));
}

6. Conclusion

In this article, we have introduced Spring LDAP APIs and developed simple methods for user authentication, user search, user creation and modification in an LDAP server.

As always the full source code is available in this Github project. The tests are created under Maven profile “live” and hence can be run using the option “-P live”.

Java 9 CompletableFuture API Improvements

$
0
0

1. Introduction

Java 9 comes with some changes to the CompletableFuture class. Such changes were introduced as part of JEP 266 in order to address common complaints and suggestions since its introduction in JDK 8, more specifically, support for delays and timeouts, better support for subclassing and a few utility methods.

Code-wise, the API comes with eight new methods and five new static methods. To enable such additions, approximately, 1500 out of 2400 lines of code were changed (as per Open JDK).

2. Instance API Additions

As mentioned, the instance API comes with eight new additions, they are:

  1. Executor defaultExecutor()
  2. CompletableFuture<U> newIncompleteFuture()
  3. CompletableFuture<T> copy()
  4. CompletionStage<T> minimalCompletionStage()
  5. CompletableFuture<T> completeAsync(Supplier<? extends T> supplier, Executor executor)
  6. CompletableFuture<T> completeAsync(Supplier<? extends T> supplier)
  7. CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)
  8. CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

2.1. Method defaultExecutor()

Signature: Executor defaultExecutor()

Returns the default Executor used for async methods that do not specify an Executor.

new CompletableFuture().defaultExecutor()

This can be overridden by subclasses returning an executor providing, at least, one independent thread.

2.2. Method newIncompleteFuture()

Signature: CompletableFuture<U> newIncompleteFuture()

The newIncompleteFuture, also known as the “virtual constructor”, is used to get a new completable future instance of the same type.

new CompletableFuture().newIncompleteFuture()

This method is especially useful when subclassing CompletableFuture, mainly because it is used internally in almost all methods returning a new CompletionStage, allowing subclasses to control what subtype gets returned by such methods.

2.3. Method copy()

Signature: CompletableFuture<T> copy()

This method returns a new CompletableFuture which:

  • When this gets completed normally, the new one gets completed normally also
  • When this gets completed exceptionally with exception X, the new one is also completed exceptionally with a CompletionException with X as cause
new CompletableFuture().copy()

This method may be useful as a form of “defensive copying”, to prevent clients from completing, while still being able to arrange dependent actions on a specific instance of CompletableFuture.

2.4. Method minimalCompletionStage()

Signature: CompletionStage<T> minimalCompletionStage()

This method returns a new CompletionStage which behaves in the exact same way as described by the copy method, however, such new instance throws UnsupportedOperationException in every attempt to retrieve or set the resolved value.

new CompletableFuture().minimalCompletionStage()

A new CompletableFuture with all methods available can be retrieved by using the toCompletableFuture method available on the CompletionStage API.

2.5. Methods completeAsync()

The completeAsync method should be used to complete the CompletableFuture asynchronously using the value given by the Supplier provided.

Signatures:

CompletableFuture<T> completeAsync(Supplier<? extends T> supplier, Executor executor)
CompletableFuture<T> completeAsync(Supplier<? extends T> supplier)

The difference between this two overloaded methods is the existence of the second argument, where the Executor running the task can be specified. If none is provided, the default executor (returned by the defaultExecutor method) will be used.

2.6. Methods orTimeout()

Signature: CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)

new CompletableFuture().orTimeout(1, TimeUnit.SECONDS)

Resolves the CompletableFuture exceptionally with TimeoutException, unless it is completed before the specified timeout.

2.7. Method completeOnTimeout()

Signature: CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

new CompletableFuture().completeOnTimeout(value, 1, TimeUnit.SECONDS)

Completes the CompletableFuture normally with the specified value unless it is completed before the specified timeout.

3. Static API Additions

Some utility methods were also added. They are:

  1. Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
  2. Executor delayedExecutor(long delay, TimeUnit unit) 
  3. <U> CompletionStage<U> completedStage(U value) 
  4. <U> CompletionStage<U> failedStage(Throwable ex) 
  5. <U> CompletableFuture<U> failedFuture(Throwable ex)

3.1. Methods delayedExecutor

Signatures:

Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
Executor delayedExecutor(long delay, TimeUnit unit)

Returns a new Executor that submits a task to the given base executor after the given delay (or no delay if non-positive). Each delay commences upon invocation of the returned executor’s execute method. If no executor is specified the default executor (ForkJoinPool.commonPool()) will be used.

3.2. Methods completedStage and failedStage

Signatures:

<U> CompletionStage<U> completedStage(U value)
<U> CompletionStage<U> failedStage(Throwable ex)

This utility methods return already resolved CompletionStage instances, either completed normally with a value (completedStage) or completed exceptionally (failedStage) with the given exception.

3.3. Method failedFuture

Signature: <U> CompletableFuture<U> failedFuture(Throwable ex)

The failedFuture method adds the ability to specify an already completed exceptionally CompleatebleFuture instance.

4. Example Use Cases

Within this section, one will show some examples on how to use some of the new API.

4.1. Delay

This example will show how to delay the completion of a CompletableFuture with a specific value by one second. That can be achieved by using the completeAsync method together with the delayedExecutor.

CompletableFuture<Object> future = new CompletableFuture<>();
future.completeAsync(() -> input, CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));

4.2. Complete with Value on Timeout

Another way to achieve a delayed result is to use the completeOnTimeout method. This example defines a CompletableFuture that will be resolved with a given input if it stays unresolved after 1 second.

CompletableFuture<Object> future = new CompletableFuture<>();
future.completeOnTimeout(input, 1, TimeUnit.SECONDS);

4.3. Timeout

Another possibility is timing out which resolves the future exceptionally with TimeoutException.  For example, having the CompletableFuture timing out after 1 second given it is not completed before that.

CompletableFuture<Object> future = new CompletableFuture<>();
future.orTimeout(1, TimeUnit.SECONDS);

5. Conclusion

In conclusion, Java 9 comes with several additions to the CompletableFuture API, it now has better support for subclassing, thanks to the newIncompleteFuture virtual constructor, it is possible to take control over the CompletionStage instances returned in most of the CompletionStage API.

It has, definitely, better support for delays and timeouts as shown previously. The utility methods added follow a sensible pattern, giving CompletableFuture a convenient way to specify resolved instances.

The examples used in this article can be found in our GitHub repository.

[NEWS] AssertJ 3.6.X – Interview with Joel Costigliola

$
0
0

1. Introduction

AssertJ is a library that provides fluent assertions for Java. You can read more about it here and here.

Recently, the 3.6.0 version was released along with two small bug-fix releases 3.6.1 and 3.6.2.

Today, Joel Costigliola – the creator of the library – is with us and will tell you a little bit more about the release and future plans.

“We are trying to make AssertJ really community-oriented”

2. Versions 2.6.0 and 3.6.0 were released pretty much at the same time. What is the difference between them? 

2.x versions target Java 7 while 3.x target Java 8. Another way of seeing this is that 3.x = 2.x + Java 8 specific features.

3. What are the most notable changes/additions that appeared in 3.6.0/2.6.0?

2.6.0 ended up having different small features but no big additions. If I had to choose, the most interesting ones would be those related to suppresed exceptions:
hasSuppresedException()
– hasNoSuppresedExceptions()

3.6.0 additionally got a way of checking multiples assertions on array/iterable/map entry elements:

4. Since the release of 3.6.0 two bugfix releases appeared (3.6.1, 3.6.2). Can you tell us a little bit more what happened there and what needed to be fixed?

In 3.6.1, filteredOn(Predicate) was only working with List but not Iterable, pretty bad.

In 3.6.2, we did not think of extracting properties from Java 8 default getter method, it turns out it did not work out of the box after some internal refactoring.

I asked users whether they could wait for the next release, the bug reporter told me he was ok to wait but another user wanted it so I released a new version. We are trying to make AssertJ really community-oriented, since cutting as release is cheap (well except the documentation part) I usually don’t see any problem releasing.

5. Did you encounter any interesting technical challenges when working on the newest release?

I will point a problem I have encountered working on the next release 3.7.0 that should be out in few weeks.

Java 8 is picky about “ambiguous” method signatures. We added a new assertThat method that takes a ThrowingCallable (a simple class that is a Callable throwing an exception), it turned out that Java 8 confuses it with another assertThat method that takes an Iterable!

That was the most surprising to me as I don’t see any ambiguity between the two.

6. Are you planning any new major release soon? Anything that will utilize Java 9 additions?

In the next weeks / one month. We usually try to have releases every few months or when there are major additions.

Pascal Schumacher that has joined the AssertJ team has done some work on Java 9 to check compatibiliy, a few things don’t work, mainly the ones that rely on introspection since Java 9 changes the access rules. What we will do is start a 4.x branch that will be Java 9 focused, following the same strategy as 3.x vs 2.x, we will have 4.x = 3.x + Java 9 features.

Once 4.0 is officially released we will likely drop 2.x active development but keep accepting PRs as we do not have the capacity of maintaining 3 versions in sync, I mean by that we report any changes from n.x version to the n+1.x version, so adding something in 2.x would need to reported both in 3.x and 4.x and that is too much work at the moment.

A Guide to Redis with Redisson

$
0
0

1. Overview

Redisson is a Redis client for Java. In this article, we will explore some of its features, and demonstrate how it could facilitate building distributed business applications.

Redisson constitutes an in-memory data grid that offers distributed Java objects and services backed by Redis. It’s distributed in-memory data model allows sharing of domain objects and services across applications and servers.

This article will guide us on how to setup Redisson, understand how it operates, and explore some of Redisson’s objects and services.

2. Maven Dependencies

Let’s get started by importing Redisson to our project by adding the section below to our pom.xml:

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.3.0</version>
</dependency>

The latest version of this dependency can be found here.

3. Configuration

Before we get started, we must ensure we have the latest version of Redis setup and running. If you don’t have Redis and you use Linux or Macintosh, you can follow the information here to get it setup. If you are a Windows user, you can setup Redis using this unofficial port.

We need to configure Redisson to connect to Redis. Redisson supports connections to the following Redis configurations:

  • Single node
  • Master with slave nodes
  • Sentinel nodes
  • Clustered nodes
  • Replicated nodes

Redisson supports Amazon Web Services (AWS) ElastiCache Cluster and Azure Redis Cache for Clustered and Replicated Nodes.

Let’s connect to a single node instance of Redis. This instance is running locally on the default port, 6379:

RedissonClient client = Redisson.create();

You can pass different configurations to the Redisson object’s create method. This could be configurations to have it connect to a different port, or maybe, to connect to a Redis cluster. This configuration could be in Java code or loaded from an external configuration file.

3.1. Java Configuration

Let’s configure Redisson in Java code:

Config config = new Config();
config.useSingleServer()
  .setAddress("127.0.0.1:6379");

RedissonClient client = Redisson.create(config);

We specify Redisson configurations in an instance of a Config object and then pass it to the create method. Above, we specified to Redisson that we want to connect to a single node instance of Redis. To do this we used the Config object’s useSingleServer method. This returns a reference to a SingleServerConfig object.

The SingleServerConfig object has settings that Redisson uses to connect to a single node instance of Redis. Here, we use its setAddress method to configure the address setting. This sets the address of the node we are connecting to. Some other settings include retryAttempts, connectionTimeout and clientName. These settings are configured using their corresponding setter methods.

We can configure Redisson for different Redis configurations in a similar way using the Config object’s following methods:

  • useSingleServer – for single node instance. Get single node settings here
  • useMasterSlaveServers – for master with slave nodes. Get master-slave node settings here
  • useSentinelServers – for sentinel nodes. Get sentinel node settings here
  • useClusterServers – for clustered nodes. Get clustered node settings here
  • useReplicatedServers – for replicated nodes. Get replicated node settings here

3.2. File Configuration

Redisson can load configurations from external JSON or YAML files:

Config config = Config.fromJSON(new File("singleNodeConfig.json"));  
RedissonClient client = Redisson.create(config);

The Config object’s fromJSON method can load configurations from a string, file, input stream or URL.

Here is the sample configuration in the singleNodeConfig.json file:

{
    "singleServerConfig": {
        "idleConnectionTimeout": 10000,
        "pingTimeout": 1000,
        "connectTimeout": 10000,
        "timeout": 3000,
        "retryAttempts": 3,
        "retryInterval": 1500,
        "reconnectionTimeout": 3000,
        "failedAttempts": 3,
        "password": null,
        "subscriptionsPerConnection": 5,
        "clientName": null,
        "address": "redis://127.0.0.1:6379",
        "subscriptionConnectionMinimumIdleSize": 1,
        "subscriptionConnectionPoolSize": 50,
        "connectionMinimumIdleSize": 10,
        "connectionPoolSize": 64,
        "database": 0,
        "dnsMonitoring": false,
        "dnsMonitoringInterval": 5000
    },
    "threads": 0,
    "nettyThreads": 0,
    "codec": null,
    "useLinuxNativeEpoll": false
}

Here is a corresponding YAML configuration file:

singleServerConfig:
    idleConnectionTimeout: 10000
    pingTimeout: 1000
    connectTimeout: 10000
    timeout: 3000
    retryAttempts: 3
    retryInterval: 1500
    reconnectionTimeout: 3000
    failedAttempts: 3
    password: null
    subscriptionsPerConnection: 5
    clientName: null
    address: "redis://127.0.0.1:6379"
    subscriptionConnectionMinimumIdleSize: 1
    subscriptionConnectionPoolSize: 50
    connectionMinimumIdleSize: 10
    connectionPoolSize: 64
    database: 0
    dnsMonitoring: false
    dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
useLinuxNativeEpoll: false

We can configure other Redis configurations from a file in a similar manner using settings peculiar to that configuration. For your reference, here are their JSON and YAML file formats:

To save a Java configuration to JSON or YAML format, we can use the toJSON or toYAML methods of the Config object:

Config config = new Config();
// ... we configure multiple settings here in Java
String jsonFormat = config.toJSON();
String yamlFormat = config.toYAML();

Now that we know how to configure Redisson, let’s look at how Redisson executes operations.

4. Operation

Redisson supports synchronous, asynchronous and reactive interfaces. Operations over these interfaces are thread-safe.

All entities (objects, collections, locks and services) generated by a RedissonClient have synchronous and asynchronous methods. Synchronous methods bear asynchronous variants. These methods normally bear the same method name of their synchronous variants appended with “Async”. Let’s look at a synchronous method of the RAtomicLong object:

RedissonClient client = Redisson.create();
RAtomicLong myLong = client.getAtomicLong('myLong');

The asynchronous variant of the synchronous compareAndSet method would be:

RFuture<Boolean> isSet = myLong.compareAndSetAsync(6, 27);

The asynchronous variant of the method returns an RFuture object. We can set listeners on this object to get back the result when it becomes available:

isSet.handle((result, exception) -> {
    // handle the result or exception here.
});

To generate reactive objects, we would need to use the RedissonReactiveClient:

RedissonReactiveClient client = Redisson.createReactive();
RAtomicLongReactive myLong = client.getAtomicLong("myLong");

Publisher<Boolean> isSetPublisher = myLong.compareAndSet(5, 28);

This method returns reactive objects based on the Reactive Streams Standard for Java 9.

Let’s explore some of the distributed objects provided by Redisson.

5. Objects

An individual instance of a Redisson object is serialized and stored in any of the available Redis nodes backing Redisson. These objects could be distributed in a cluster across multiple nodes and can be accessed by a single application or multiple applications/servers.

These distributed objects follow specifications from the java.util.concurrent.atomic package. They support lock-free, thread-safe and atomic operations on objects stored in Redis. Data consistency between applications/servers is ensured as values are not updated while another application is reading the object.

Redisson objects are bound to Redis keys. We can manage these keys through the RKeys interface. We access our Redisson objects using these keys.

We can get all keys:

RKeys keys = client.getKeys();

We can extract all key names as iterable string collections:

Iterable<String> allKeys = keys.getKeys();

We can get keys conforming to a pattern:

Iterable<String> keysByPattern = keys.getKeysByPattern('key*')

The RKeys interface also allows deleting keys, deleting keys by pattern and other useful key-based operations that we could use to manage our keys and objects.

Distributed objects provided by Redisson include:

  • ObjectHolder
  • BinaryStreamHolder
  • GeospatialHolder
  • BitSet
  • AtomicLong
  • AtomicDouble
  • Topic
  • BloomFilter
  • HyperLogLog

Let’s take a look at three of these objects: ObjectHolder, AtomicLong, and Topic.

5.1. Object Holder

Represented by the RBucket class, this object can hold any type of object. This object has a maximum size of 512MB:

RBucket<Ledger> bucket = client.getBucket("ledger");
bucket.set(new Ledger());
Ledger ledger = bucket.get();

The RBucket object can perform atomic operations such as compareAndSet and getAndSet on objects it holds.

5.2. AtomicLong

Represented by the RAtomicLong class, this object closely resembles the java.util.concurrent.atomic.AtomicLong class and represents a long value that can be updated atomically:

RAtomicLong atomicLong = client.getAtomicLong("myAtomicLong");
atomicLong.set(5);
atomicLong.incrementAndGet();

5.3. Topic

The Topic object supports the Redis’ “publish and subscribe” mechanism. To listen for published messages:

RTopic<CustomMessage> subscribeTopic = client.getTopic("baeldung");
subscribeTopic.addListener(
  (channel, customMessage) 
  -> future.complete(customMessage.getMessage()));

Above, the Topic is registered to listen to messages from the “baeldung” channel. We then add a listener to the topic to handle incoming messages from that channel. We can add multiple listeners to a channel.

Let’s publish messages to the “baeldung” channel:

RTopic<CustomMessage> publishTopic = client.getTopic("baeldung");
long clientsReceivedMessage
  = publishTopic.publish(new CustomMessage("This is a message"));

This could be published from another application or server. The CustomMessage object will be received by the listener and processed as defined in the onMessage method.

We can learn more about other Redisson objects here.

6. Collections

We handle Redisson collections in the same fashion we handle objects.

Distributed collections provided by Redisson include:

  • Map
  • Multimap
  • Set
  • SortedSet
  • ScoredSortedSet
  • LexSortedSet
  • List
  • Queue
  • Deque
  • BlockingQueue
  • BoundedBlockingQueue
  • BlockingDeque
  • BlockingFairQueue
  • DelayedQueue
  • PriorityQueue
  • PriorityDeque

Let’s take a look at three of these collections: Map, Set, and List.

6.1. Map

Redisson based maps implement the java.util.concurrent.ConcurrentMap and java.util.Map interfaces. Redisson has four map implementations. These are RMap, RMapCache, RLocalCachedMap and RClusteredMap.

Let’s create a map with Redisson:

RMap<String, Ledger> map = client.getMap("ledger");
Ledger newLedger = map.put("123", new Ledger());map

RMapCache supports map entry eviction. RLocalCachedMap allows local caching of map entries. RClusteredMap allows data from a single map to be split across Redis cluster master nodes.

We can learn more about Redisson maps here.

6.2. Set

Redisson based Set implements the java.util.Set interface.

Redisson has three Set implementations, RSet, RSetCache, and RClusteredSet with similar functionality as their map counterparts.

Let’s create a Set with Redisson:

RSet<Ledger> ledgerSet = client.getSet("ledgerSet");
ledgerSet.add(new Ledger());

We can learn more about Redisson sets here.

6.3. List

Redisson-based Lists implement the java.util.List interface.

Let’s create a List with Redisson:

RList<Ledger> ledgerList = client.getList("ledgerList");
ledgerList.add(new Ledger());

We can learn more about other Redisson collections here.

7. Locks and Synchronizers

Redisson’s distributed locks allow for thread synchronization across applications/servers. Redisson’s list of locks and synchronizers include:

  • Lock
  • FairLock
  • MultiLock
  • ReadWriteLock
  • Semaphore
  • PermitExpirableSemaphore
  • CountDownLatch

Let’s take a look at Lock and MultiLock.

7.1. Lock

Redisson’s Lock implements java.util.concurrent.locks.Lock interface.

Let’s implement a lock, represented by the RLock class:

RLock lock = client.getLock("lock");
lock.lock();
// perform some long operations...
lock.unlock();

7.2. MultiLock

Redisson’s RedissonMultiLock groups multiple RLock objects and treats them as a single lock:

RLock lock1 = clientInstance1.getLock("lock1");
RLock lock2 = clientInstance2.getLock("lock2");
RLock lock3 = clientInstance3.getLock("lock3");

RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
// perform long running operation...
lock.unlock();

We can learn more about other locks here.

8. Services

Redisson exposes 4 types of distributed services. These are: Remote Service, Live Object Service, Executor Service and Scheduled Executor Service. Let’s look at the Remote Service and Live Object Service.

8.1. Remote Service

This service provides Java remote method invocation facilitated by Redis. A Redisson remote service consists of a server-side (worker instance) and client-side implementation. The server-side implementation executes a remote method invoked by the client. Calls from a remote service can be synchronous or asynchronous.

The server-side registers an interface for remote invocation:

RRemoteService remoteService = client.getRemoteService();
LedgerServiceImpl ledgerServiceImpl = new LedgerServiceImpl();

remoteService.register(LedgerServiceInterface.class, ledgerServiceImpl);

The client-side calls a method of the registered remote interface:

RRemoteService remoteService = client.getRemoteService();
LedgerServiceInterface ledgerService
  = remoteService.get(LedgerServiceInterface.class);

List<String> entries = ledgerService.getEntries(10);

We can learn more about remote services here.

8.2. Live Object Service

Redisson Live Objects extend the concept of standard Java objects that could only be accessed from a single JVM to enhanced Java objects that could be shared between different JVMs in different machines. This is accomplished by mapping an object’s fields to a Redis hash. This mapping is made through a runtime-constructed proxy class. Field getters and setters are mapped to Redis hget/hset commands.

Redisson Live Objects support atomic field access as a result of Redis’ single-threaded nature.

Creating a Live Object is simple:

@REntity
public class LedgerLiveObject {
    @RId
    private String name;

    // getters and setters...
}

We annotate our class with @REntity and a unique or identifying field with @RId. Once we have done this, we can use our Live Object in our application:

RLiveObjectService service = client.getLiveObjectService();

LedgerLiveObject ledger = new LedgerLiveObject();
ledger.setName("ledger1");

ledger = service.persist(ledger);

We create our Live Object like standard Java objects using the new keyword. We then use an instance of RLiveObjectService to save the object to Redis using its persist method.

If the object has previously been persisted to Redis, we can retrieve the object:

LedgerLiveObject returnLedger
  = service.get(LedgerLiveObject.class, "ledger1");

We use the RLiveObjectService to get our Live Object using the field annotated with @RId.

We can learn more about Redisson Live Objects here.

We can also learn more about other Redisson services here.

9. Pipelining

Redisson supports pipelining. Multiple operations can be batched as a single atomic operation. This is facilitated by the RBatch class. Multiple commands are aggregated against an RBatch object instance before they are executed:

RBatch batch = client.createBatch();
batch.getMap("ledgerMap").fastPutAsync("1", "2");
batch.getMap("ledgerMap").putAsync("2", "5");

List<?> result = batch.execute();

10. Scripting

Redisson supports LUA scripting. We can execute LUA scripts against Redis:

client.getBucket("foo").set("bar");
String result = client.getScript().eval(Mode.READ_ONLY,
  "return redis.call('get', 'foo')", RScript.ReturnType.VALUE);

11. Low-Level Client

It is possible that we might want to perform Redis operations not yet supported by Redisson. Redisson provides a low-level client that allows execution of native Redis commands:

RedisClient client = new RedisClient("localhost", 6379);
RedisConnection conn = client.connect();
conn.sync(StringCodec.INSTANCE, RedisCommands.SET, "test", 0);

conn.closeAsync();
client.shutdown();

The low-level client also supports asynchronous operations.

12. Conclusion

This article showcased Redisson and some of the features that make it ideal for developing distributed applications. We explored its distributed objects, collections, locks and services. We also explored some of its other features such as pipelining, scripting and its low-level client.

Redisson also provides integration with other frameworks such as the JCache API, Spring Cache, Hibernate Cache and Spring Sessions. We can learn more about its integration with other frameworks here.

You can find code samples in the GitHub project.

Guide to Google Guice

$
0
0

1. Introduction

This article will examine the fundamentals of Google Guice. We’ll look at approaches to completing basic Dependency Injection (DI) tasks in Guice.

We will also compare and contrast the Guice approach to those of more established DI frameworks like Spring and Contexts and Dependency Injection (CDI).

This article presumes the reader has an understanding of the fundamentals of the Dependency Injection pattern.

2. Setup

In order to use Google Guice in your Maven project, you will need to add the following dependency to your pom.xml:

<dependency>
    <groupId>com.google.inject</groupId>
    <artifactId>guice</artifactId>
    <version>4.1.0</version>
</dependency>

There is also a collection of Guice extensions (we will cover those a little later) here, as well as third-party modules to extend the capabilities of Guice (mainly by providing integration to more established Java frameworks).

3. Basic Dependency Injection With Guice

3.1. Our Sample Application

We will be working with a scenario where we design classes that support three means of communication in a helpdesk business: Email, SMS, and IM.

Consider the class:

public class Communication {
 
    @Inject 
    private Logger logger;
    
    @Inject
    private Communicator communicator;

    public Communication(Boolean keepRecords) {
        if (keepRecords) {
            System.out.println("Message logging enabled");
        }
    }
 
    public boolean sendMessage(String message) {
        return communicator.sendMessage(message);
    }

}

This Communication class is the basic unit of communication. An instance of this class is used to send messages via the available communications channels. As shown above, Communication has a Communicator which we use to do the actual message transmission.

The basic entry point into Guice is the Injector:

public static void main(String[] args){
    Injector injector = Guice.createInjector(new BasicModule());
    Communication comms = injector.getInstance(Communication.class);
}

This main method retrieves an instance of our Communication class. It also introduces a fundamental concept of Guice: the Module (using BasicModule in this example). The Module is the basic unit of definition of bindings (or wiring, as it’s known in Spring).

Guice has adopted a code-first approach for dependency injection and management so you won’t be dealing with a lot of XML out-of-the-box.

In the example above, the dependency tree of Communication will be implicitly injected using a feature called just-in-time binding, provided the classes have the default no-arg constructor. This has been a feature in Guice since inception and only available in Spring since v4.3.

3.2. Guice Bindings

Binding is to Guice as wiring is to Spring. With bindings, you define how Guice is going to inject dependencies into a class.

A binding is defined in an implementation of com.google.inject.AbstractModule:

public class BasicModule extends AbstractModule {
 
    @Override
    protected void configure() {
        bind(Communicator.class).to(DefaultCommunicatorImpl.class);
    }
}

This module implementation specifies that an instance of DefaultCommunicatorImpl is to be injected wherever a Communicator variable is found.

Another incarnation of this mechanism is the named binding. Consider the following variable declaration:

@Inject @Named("DefaultCommunicator")
Communicator communicator;

For this, we will have the following binding definition:

@Override
protected void configure() {
    bind(Communicator.class)
      .annotatedWith(Names.named("DefaultCommunicator"))
      .to(Communicator.class);
}

This binding will provide an instance of Communicator to a variable annotated with the @Named(“DefaultCommunicator”) annotation.

You’ll notice the @Inject and @Named annotations appear to be loan annotations from JavaEE’s CDI, and they are. They are in the com.google.inject.* package — you should be careful to import from the right package when using an IDE.

Tip: While we just said to use the Guice-provided @Inject and @Named, it’s worthwhile to note that Guice does provide support for javax.inject.Inject and javax.inject.Named, among other JavaEE annotations.

You can also inject a dependency that doesn’t have a default no-arg constructor using constructor binding:

public class BasicModule extends AbstractModule {
 
    @Override
    protected void configure() {
        bind(Boolean.class).toInstance(true);
        bind(Communication.class).toConstructor(
          Communication.class.getConstructor(Boolean.TYPE));
}

The snippet above will inject an instance of Communication using the constructor that takes a boolean argument. We supply the true argument to the constructor by defining an untargeted binding of the Boolean class.

This untargeted binding will be eagerly supplied to any constructor in the binding that accepts a boolean parameter. With this approach, all dependencies of Communication are injected.

Another approach to constructor-specific binding is the instance binding, where we provide an instance directly in the binding:

public class BasicModule extends AbstractModule {
 
    @Override
    protected void configure() {
        bind(Communication.class)
          .toInstance(new Communication(true));
    }    
}

This binding will provide an instance of the Communication class wherever a Communication variable is declared.

In this case, however, the dependency tree of the class will not be automatically wired. You should limit the use of this mode where there isn’t any heavy initialization or dependency injection necessary.

4. Types of Dependency Injection

Guice supports the standard types of injections you would have come to expect with the DI pattern. In the Communicator class, we need to inject different types of CommunicationMode.

4.1. Field Injection

@Inject @Named("SMSComms")
CommunicationMode smsComms;

Use the optional @Named annotation as a qualifier to implement targeted injection based on the name

4.2. Method Injection

Here we use a setter method to achieve the injection:

@Inject
public void setEmailCommunicator(@Named("EmailComms") CommunicationMode emailComms) {
    this.emailComms = emailComms;
}

4.3. Constructor Injection

You can also inject dependencies using a constructor:

@Inject
public Communication(@Named("IMComms") CommunicationMode imComms) {
    this.imComms= imComms;
}

4.4. Implicit Injections

Guice will implicitly inject some general purpose components like the Injector and an instance of java.util.Logger, among others. You’ll notice we are using loggers all through the samples but you won’t find an actual binding for them.

5. Scoping in Guice

Guice supports the scopes and scoping mechanisms we have grown used to in other DI frameworks. Guice defaults to providing a new instance of a defined dependency.

5.1. Singleton

Let’s inject a singleton into our application:

bind(Communicator.class).annotatedWith(Names.named("AnotherCommunicator"))
  .to(Communicator.class).in(Scopes.SINGLETON);

The in(Scopes.SINGLETON) specifies that any Communicator field with the @Named(“AnotherCommunicator”) will get a singleton injected. This singleton is lazily initiated by default.

5.2. Eager Singleton

Now, let’s inject an eager singleton:

bind(Communicator.class).annotatedWith(Names.named("AnotherCommunicator"))
  .to(Communicator.class)
  .asEagerSingleton();

The asEagerSingleton() call defines the singleton as eagerly instantiated.

In addition to these two scopes, Guice supports custom scopes as well as the web-only @RequestScoped and @SessionScoped annotations, supplied by JavaEE (there are no Guice-supplied versions of those annotations).

6. Aspect Oriented Programming in Guice

Guice is compliant with the AOPAlliance’s specifications for aspect-oriented programming. We can implement the quintessential logging interceptor, which we will use to track message sending in our example, in only four steps.

Step 1 –  Implement the AOPAlliance’s MethodInterceptor:

public class LoggingInterceptor implements MethodInterceptor {

    @Inject
    Logger logger;

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object[] objectArray = invocation.getArguments();
        int i = 0;
        for (Object object : objectArray) {
            logger.info("Sending message: " + object.toString());
        }
        return invocation.proceed();
    }
}

Step 2 – Define a plain java annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MessageSentLoggable {
}

Step 3 – Define a binding for a Matcher:

Matcher is a Guice class that we use do specify the components that our AOP annotation will apply to. In this case, we want the annotation to apply to implementations of CommunicationMode:

public class AOPModule extends AbstractModule {

    @Override
    protected void configure() {
        bindInterceptor(
            Matchers.any(),
            Matchers.annotatedWith(MessageSentLoggable.class),
            new MessageLogger()
        );
    }
}

We have specified a Matcher here that will apply our MessageLogger interceptor to any class, that has the MessageSentLoggable annotation applied to its methods.

Step 4 – Apply our annotation to our CommunicationMode and load our Module

@Override
@MessageSentLoggable
public boolean sendMessage(String message) {
    logger.info("SMS message sent");
    return true;
}

public static void main(String[] args) {
    Injector injector = Guice.createInjector(new BasicModule(), new AOPModule());
    Communication comms = injector.getInstance(Communication.class);
}

7. Conclusion

Having looked at basic Guice functionality, we can see where the inspiration for Guice came from Spring.

Along with its support for JSR-330, Guice aims to be an injection-focused DI framework (whereas Spring provides a whole ecosystem for programming convenience not necessarily just DI), targeted at developers who want DI flexibility.

Guice is also highly extensible, allowing programmers to write portable plugins that result in flexible and creative uses of the framework. This is in addition to the extensive integration that Guice already provides for most popular frameworks and platforms like Servlets, JSF, JPA, and OSGi, to name a few.

You can find all of the source code used in this tutorial in our GitHub project.

Multiple Entry Points in Spring Security

$
0
0

1. Overview

In this quick tutorial, we’re going to take a look at how to define multiple entry points in a Spring Security application.

This mainly entails defining multiple http blocks in an XML configuration file or multiple HttpSecurity instances by extending the WebSecurityConfigurerAdapter class multiple times.

2. Maven Dependencies

For development, we will need the following dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>1.5.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>1.5.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>1.5.2.RELEASE</version>
</dependency>    
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <version>4.2.2.RELEASE</version>
</dependency>

The latest versions of spring-boot-starter-security, spring-boot-starter-thymeleaf, spring-boot-starter-test, spring-security-test can be downloaded from Maven Central.

3. Defining Multiple Entry Points

3.1. Java Configuration

Let’s define the main configuration class that will hold a user source:

@Configuration
@EnableWebSecurity
public class MultipleEntryPointsSecurityConfig {

    @Bean
    public UserDetailsService userDetailsService() throws Exception {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User
          .withUsername("user")
          .password("userPass")
          .roles("USER").build());
        manager.createUser(User
          .withUsername("admin")
          .password("adminPass")
          .roles("ADMIN").build());
        return manager;
    }
}

When using Java configuration, the way to define multiple security realms is to define multiple configuration classes extending the WebSecurityConfigurerAdapter – each having its own security configuration. These can be static classes inside the main @Configuration class.

The main motivation for having multiple entry points in one application is if there are different types of users that can access different portions of the application.

Let’s look at an example – and define a configuration with three entry points, each having different permissions and authentication modes: one for administrative users using HTTP Basic Authentication, one for regular users that use form authentication, and one for guest users that do not require authentication.

The entry point defined for administrative users secures URLs of the form /admin/** to only allow users with a role of ADMIN and requires HTTP Basic Authentication:

@Configuration
@Order(1)
public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/admin/**")
            .authorizeRequests().anyRequest().hasRole("ADMIN")
            .and().httpBasic()
            .and().exceptionHandling().accessDeniedPage("/403");
    }
}

The @Order annotation on each static class indicates the order in which the configurations will be considered to find one that matches the requested URL. The order value for each class must be unique.

Next, let’s define the configuration for URLs of the form /user/** that can be accessed by regular users with a USER role using form authentication:

@Configuration
@Order(2)
public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter {

    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/user/**")
            .authorizeRequests().anyRequest().hasRole("USER")
            .and()
            .formLogin().loginPage("/userLogin").loginProcessingUrl("/user/login")
            .failureUrl("/userLogin?error=loginError")
            .defaultSuccessUrl("/user/myUserPage")
            .and()
            .logout().logoutUrl("/user/logout")
            .logoutSuccessUrl("/multipleHttpLinks")
            .deleteCookies("JSESSIONID")
            .and()
            .exceptionHandling().accessDeniedPage("/403")
            .and()
            .csrf().disable();
    }
}

This configuration will also require defining the /userLogin MVC mapping and a page that contains a standard login form.

For the form authentication, it’s very important to remember that any URL necessary for the configuration, such as the login processing URL also needs to follow the /user/** format or be otherwise configured to be accessible.

Both of the above configurations will redirect to a /403 URL if a user without the appropriate role attempts to access a protected URL.

Finally, let’s define the third configuration for URLs of the form /guest/** that will allow all types of users, including unauthenticated ones:

@Configuration
@Order(3)
public static class App3ConfigurationAdapter extends WebSecurityConfigurerAdapter {

    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/guest/**").authorizeRequests().anyRequest().permitAll();
    }
}

3.2. XML Configuration

Let’s take a look at the equivalent XML configuration for the three HttpSecurity instances in the previous section.

This will contain three separate XML <http> blocks.

For the /admin/** URLs the XML configuration will be:

<security:http pattern="/admin/**" use-expressions="true" auto-config="true">
    <security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"/>
    <security:http-basic/>
    <security:access-denied-handler error-page="/403"/>
</security:http>

Of note here is that if using XML configuration, the roles have to be of the form ROLE_<ROLE_NAME>.

The configuration for the /user/** URLs is:

<security:http pattern="/user/**" use-expressions="true" auto-config="true">
    <security:intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
    <security:form-login login-page="/userLogin" login-processing-url="/user/login" 
      authentication-failure-url="/userLogin?error=loginError"
      default-target-url="/user/myUserPage"/>
    <security:csrf disabled="true"/>
    <security:access-denied-handler error-page="/403"/>
    <security:logout logout-url="/user/logout" delete-cookies="JSESSIONID" 
      logout-success-url="/multipleHttpLinks"/>
</security:http>

For the /guest/** URLs we will have the http element:

<security:http pattern="/**" use-expressions="true" auto-config="true">
    <security:intercept-url pattern="/guest/**" access="permitAll()"/>  
</security:http>

Also important here is that at least one XML <http> block must match the /** pattern.

4. Accessing Protected URLs

4.1. MVC Configuration

Let’s create request mappings that match the URL patterns we have secured:

@Controller
public class PagesController {

    @RequestMapping("/admin/myAdminPage")
    public String getAdminPage() {
        return "multipleHttpElems/myAdminPage";
    }

    @RequestMapping("/user/myUserPage")
    public String getUserPage() {
        return "multipleHttpElems/myUserPage";
    }

    @RequestMapping("/guest/myGuestPage")
    public String getGuestPage() {
        return "multipleHttpElems/myGuestPage";
    }

    @RequestMapping("/403")
    public String getAccessDeniedPage() {
        return "403";
    }
    @RequestMapping("/multipleHttpLinks")
    public String getMultipleHttpLinksPage() {
        return "multipleHttpElems/multipleHttpLinks";
    }
}

The /multipleHttpLinks mapping will return a simple HTML page with links to the protected URLs:

<a th:href="@{/admin/myAdminPage}">Admin page</a>
<a th:href="@{/user/myUserPage}">User page</a>
<a th:href="@{/guest/myGuestPage}">Guest page</a>

Each of the HTML pages corresponding to the protected URLs will have a simple text and a back link:

Welcome admin!

<a th:href="@{/multipleHttpLinks}" >Back to links</a>

4.2. Initializing the Application

We will run our example as a Spring Boot application, so let’s define a class with the main method:

@SpringBootApplication
public class MultipleEntryPointsApplication {
    public static void main(String[] args) {
        SpringApplication.run(MultipleEntryPointsApplication.class, args);
    }
}

If we want to use the XML configuration, we also need to add the @ImportResource({“classpath*:spring-security-multiple-entry.xml”}) annotation to our main class.

4.3. Testing the Security Configuration

Let’s set up a JUnit test class that we can use to test our protected URLs:

@RunWith(SpringRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = MultipleEntryPointsApplication.class)
public class MultipleEntryPointsTest {
 
    @Autowired
    private WebApplicationContext wac;

    @Autowired
    private FilterChainProxy springSecurityFilterChain;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
          .addFilter(springSecurityFilterChain).build();
    }
}

Next, let’s test the URLs using the admin user.

When requesting the /admin/adminPage URL without an HTTP Basic Authentication, we should expect to receive an Unauthorized status code, and after adding the authentication the status code should be 200 OK.

If attempting to access the /user/userPage URL with the admin user, we should receive status 302 Forbidden:

@Test
public void whenTestAdminCredentials_thenOk() throws Exception {
    mockMvc.perform(get("/admin/myAdminPage")).andExpect(status().isUnauthorized());

    mockMvc.perform(get("/admin/myAdminPage")
      .with(httpBasic("admin", "adminPass"))).andExpect(status().isOk());

    mockMvc.perform(get("/user/myUserPage")
      .with(user("admin").password("adminPass").roles("ADMIN")))
      .andExpect(status().isForbidden());
}

Let’s create a similar test using the regular user credentials to access the URLs:

@Test
public void whenTestUserCredentials_thenOk() throws Exception {
    mockMvc.perform(get("/user/myUserPage")).andExpect(status().isFound());

    mockMvc.perform(get("/user/myUserPage")
      .with(user("user").password("userPass").roles("USER")))
      .andExpect(status().isOk());

    mockMvc.perform(get("/admin/myAdminPage")
      .with(user("user").password("userPass").roles("USER")))
      .andExpect(status().isForbidden());
}

In the second test, we can see that missing the form authentication will result in a status of 302 Found instead of Unauthorized, as Spring Security will redirect to the login form.

Finally, let’s create a test in which we access the /guest/guestPage URL will all three types of authentication and verify we receive a status of 200 OK:

@Test
public void givenAnyUser_whenGetGuestPage_thenOk() throws Exception {
    mockMvc.perform(get("/guest/myGuestPage")).andExpect(status().isOk());

    mockMvc.perform(get("/guest/myGuestPage")
      .with(user("user").password("userPass").roles("USER")))
      .andExpect(status().isOk());

    mockMvc.perform(get("/guest/myGuestPage")
      .with(httpBasic("admin", "adminPass")))
      .andExpect(status().isOk());
}

5. Conclusion

In this tutorial, we have demonstrated how to configure multiple entry points when using Spring Security.

The complete source code for the examples can be found over on GitHub. To run the application, uncomment the MultipleEntryPointsApplication start-class tag in the pom.xml and run the command mvn spring-boot:run, then accesses the /multipleHttpLinks URL

Note that it is not possible to log out when using HTTP Basic Authentication, so you will have to close and reopen the browser to remove this authentication.

To run the JUnit test, use the defined Maven profile entryPoints with the following command:

mvn clean install -PentryPoints

A Guide to the Java API for WebSocket

$
0
0

1. Overview

WebSocket provides an alternative to the limitation of efficient communication between the server and the web browser by providing bi-directional, full-duplex, real-time client/server communications. The server can send data to the client at any time. Because it runs over TCP, it also provides a low-latency low-level communication and reduces the overhead of each message.

In this article, we’ll take a look at the Java API for WebSockets by creating a chat-like application.

2. JSR 356

JSR 356 or the Java API for WebSocket, specifies an API that Java developers can use for integrating WebSockets withing their applications – both on the server side as well as on the Java client side.

This Java API provides both server and client side components:

  • Server: everything in the javax.websocket.server package.
  • Client: the content of javax.websocket package, which consists of client side APIs and also common libraries to both server and client.

3. Building a Chat Using WebSockets

We will build a very simple chat-like application. Any user will be able to open the chat from any browser, type his name, login into the chat and start communicating with everybody connected to the chat.

We’ll start by adding the latest dependency to the pom.xml file:

<dependency>
    <groupId>javax.websocket</groupId
    <artifactId>javax.websocket-api</artifactId>
    <version>1.1</version>
</dependency>

The latest version may be found here.

In order to convert Java Objects into their JSON representations and vice versa, we’ll use Gson:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.0</version>
</dependency>

The latest version is available in the Maven Central repository.

3.1. Endpoint Configuration

There are two ways of configuring endpoints: annotation-based and extension-based. You can either extend the javax.websocket.Endpoint class or use dedicated method-level annotations. As the annotation model leads to cleaner code as compared to the programmatic model, the annotation has become the conventional choice of coding. In this case, WebSocket endpoint lifecycle events are handled by the following annotations:

  • @ServerEndpoint: If decorated with @ServerEndpoint, the container ensures availability of the class as a WebSocket server listening to a specific URI space
  • @ClientEndpoint: A class decorated with this annotation is treated as a WebSocket client
  • @OnOpen: A Java method with @OnOpen is invoked by the container when a new WebSocket connection is initiated
  • @OnMessage: A Java method, annotated with @OnMessage, receives the information from the WebSocket container when a message is sent to the endpoint
  • @OnError: A method with @OnError is invoked when there is a problem with the communication
  • @OnClose: Used to decorate a Java method that is called by the container when the WebSocket connection closes

3.2. Writing the Server Endpoint

We declare a Java class WebSocket server endpoint by annotating it with @ServerEndpoint. We also specify the URI where the endpoint is deployed. The URI is defined relatively to the root of the server container and must begin with a forward slash:

@ServerEndpoint(value = "/chat/{username}")
public class ChatEndpoint {

    @OnOpen
    public void onOpen(Session session) throws IOException {
        // Get session and WebSocket connection
    }

    @OnMessage
    public void onMessage(Session session, Message message) throws IOException {
        // Handle new messages
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        // WebSocket connection closes
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        // Do error handling here
    }
}

The code above is the server endpoint skeleton for our chat-like application. As you can see, we have 4 annotations mapped to their respective methods. Below you can see the implementation of such methods:

@ServerEndpoint(value="/chat/{username}")
public class ChatEndpoint {
 
    private Session session;
    private static Set<ChatEndpoint> chatEndpoints 
      = new CopyOnWriteArraySet<>();
    private static HashMap<String, String> users = new HashMap<>();

    @OnOpen
    public void onOpen(
      Session session, 
      @PathParam("username") String username) throws IOException {
 
        this.session = session;
        chatEndpoints.add(this);
        users.put(session.getId(), username);

        Message message = new Message();
        message.setFrom(username);
        message.setContent("Connected!");
        broadcast(message);
    }

    @OnMessage
    public void onMessage(Session session, Message message) 
      throws IOException {
 
        message.setFrom(users.get(session.getId()));
        broadcast(message);
    }

    @OnClose
    public void onClose(Session session) throws IOException {
 
        chatEndpoints.remove(this);
        Message message = new Message();
        message.setFrom(users.get(session.getId()));
        message.setContent("Disconnected!");
        broadcast(message);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        // Do error handling here
    }

    private static void broadcast(Message message) 
      throws IOException, EncodeException {
 
        chatEndpoints.forEach(endpoint -> {
            synchronized (endpoint) {
                try {
                    endpoint.session.getBasicRemote().
                      sendObject(message);
                } catch (IOException | EncodeException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

When a new user logs in (@OnOpen) is immediately mapped to a data structure of active users. Then, a message is created and sent to all endpoints using the broadcast method.

This method is also used whenever a new message is sent (@OnMessage) by any of the users connected – this is the main purpose of the chat.

If at some point an error occurs, the method with the annotation @OnError handles it. You can use this method to log the information about the error and clear the endpoints.

Finally, when a user is no longer connected to the chat, the method @OnClose clears the endpoint and broadcasts to all users that a user has been disconnected.

4. Message Types

The WebSocket specification supports two on-wire data formats – text and binary. The API supports both these formats, adds capabilities to work with Java objects and health check messages (ping-pong) as defined in the specification:

  • Text: Any textual data (java.lang.String, primitives or their equivalent wrapper classes)
  • Binary: Binary data (e.g. audio, image etc.) represented by a java.nio.ByteBuffer or a byte[] (byte array)
  • Java objects: The API makes it possible to work with native (Java object) representations in your code and use custom transformers (encoders/decoders) to convert them into compatible on-wire formats (text, binary) allowed by the WebSocket protocol
  • Ping-Pong: A javax.websocket.PongMessage is an acknowledgment sent by a WebSocket peer in response to a health check (ping) request

For our application, we’ll be using Java Objects. We’ll create the classes for encoding and decoding messages.

4.1. Encoder

An encoder takes a Java object and produces a typical representation suitable for transmission as a message such as JSON, XML or binary representation. Encoders can be used by implementing the Encoder.Text<T> or Encoder.Binary<T> interfaces.

In the code below we define the class Message to be encoded and in the method encode we use Gson for encoding the Java object to JSON:

public class MessageEncoder implements Encoder.Text<Message> {

    private static Gson gson = new Gson();

    @Override
    public String encode(Message message) throws EncodeException {
        return gson.toJson(message);
    }

    @Override
    public void init(EndpointConfig endpointConfig) {
        // Custom initialization logic
    }

    @Override
    public void destroy() {
        // Close resources
    }
}

4.2. Decoder

A decoder is the opposite of an encoder and is used to transform data back into a Java object. Decoders can be implemented using the Decoder.Text<T> or Decoder.Binary<T> interfaces.

As we saw with the encoder, the decode method is where we take the JSON retrieved in the message sent to the endpoint and use Gson to transform it to a Java class called Message:

public class MessageDecoder implements Decoder.Text<Message> {

    private static Gson gson = new Gson();

    @Override
    public Message decode(String s) throws DecodeException {
        return gson.fromJson(s, Message.class);
    }

    @Override
    public boolean willDecode(String s) {
        return (s != null);
    }

    @Override
    public void init(EndpointConfig endpointConfig) {
        // Custom initialization logic
    }

    @Override
    public void destroy() {
        // Close resources
    }
}

4.3. Setting Encoder and Decoder in Server Endpoint

Let’s put everything together by adding the classes created for encoding and decoding the data at the class level annotation @ServerEndpoint:

@ServerEndpoint( 
  value="/chat/{username}", 
  decoders = MessageDecoder.class, 
  encoders = MessageEncoder.class )

Every time messages are sent to the endpoint, they will automatically either be converted to JSON or Java objects.

5. Conclusion

In this article, we looked at what is the Java API for WebSockets  and how it can help us building applications such as this real-time chat.

We saw the two programming models for creating an endpoint: annotations and programmatic. We defined an endpoint using the annotation model for our application along with the life cycle methods.

Also, in order to be able to communicate back and forth between the server and client, we saw that we need encoders and decoders to convert Java objects to JSON and vice versa.

The JSR 356 API is very simple and the annotation based programming model that makes it very easy to build WebSocket applications.

To run the application we built in the example, all we need to do is deploy the war file in a web server and go to the URL: http://localhost:8080/java-websocket/. You can find the link to the repository here.


Overview of Spring-Boot Dev Tools

$
0
0

1. Introduction

Spring Boot gives us the ability to quickly setup and run services.

To enhance the development experience further, Spring released the spring-boot-devtools tool – as part of Spring Boot-1.3. This article will try to cover the benefits we can achieve using the new functionality.

We’ll cover the following topics:

  • Property defaults
  • Automatic Restart
  • Live Reload
  • Global settings
  • Remote applications

1.1. Add Spring-Boot-Devtools in a Project

Adding spring-boot-devtools in a project is as simple as adding any other spring-boot module. In an existing spring-boot project, add the following dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

Do a clean build of the project, and you are now integrated with spring-boot-devtools. The newest version can be fetched from here and all versions can be found here.

2. Property Defaults

Spring-boot does a lot of auto-configurations, including enabling caching by default to improve performance.  One such example is caching of templates used by template engines, e.g. thymeleaf. But during development, it’s more important to see the changes as quickly as possible.

The default behavior of caching can be disabled for thymeleaf using the property spring.thymeleaf.cache=false in the application.properties file. We do not need to do this manually, introducing this spring-boot-devtools does this automatically for us.

3. Automatic Restart

In a typical application development environment, a developer would make some changes, build the project and deploy/start the application for new changes to take effect, or else try to leverage JRebel, etc.

Using spring-boot-devtools, this process is also automated. Whenever files change in the classpath, applications using spring-boot-devtools will cause the application to restart. The benefit of this feature is the time required to verify the changes made is considerably reduced:

19:45:44.804 ... - Included patterns for restart : []
19:45:44.809 ... - Excluded patterns for restart : [/spring-boot-starter/target/classes/, /spring-boot-autoconfigure/target/classes/, /spring-boot-starter-[\w-]+/, /spring-boot/target/classes/, /spring-boot-actuator/target/classes/, /spring-boot-devtools/target/classes/]
19:45:44.810 ... - Matching URLs for reloading : [file:/.../target/test-classes/, file:/.../target/classes/]

 :: Spring Boot ::        (v1.5.2.RELEASE)

2017-03-12 19:45:45.174  ...: Starting Application on machine with PID 7724 (<some path>\target\classes started by user in <project name>)
2017-03-12 19:45:45.175  ...: No active profile set, falling back to default profiles: default
2017-03-12 19:45:45.510  ...: Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@385c3ca3: startup date [Sun Mar 12 19:45:45 IST 2017]; root of context hierarchy

As seen in the logs, the thread that has spawned the application is not a main rather a restartedMain thread. Any changes made in the project be it a java file change will cause an automated restart of the project:

2017-03-12 19:53:46.204  ...: Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@385c3ca3: startup date [Sun Mar 12 19:45:45 IST 2017]; root of context hierarchy
2017-03-12 19:53:46.208  ...: Unregistering JMX-exposed beans on shutdown


 :: Spring Boot ::        (v1.5.2.RELEASE)

2017-03-12 19:53:46.587  ...: Starting Application on machine with PID 7724 (<project path>\target\classes started by user in <project name>)
2017-03-12 19:53:46.588  ...: No active profile set, falling back to default profiles: default
2017-03-12 19:53:46.591  ...: Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@acaf4a1: startup date [Sun Mar 12 19:53:46 IST 2017]; root of context hierarchy

4. Live Reload

spring-boot-devtools module includes an embedded LiveReload server that is used to trigger a browser refresh when a resource is changed.

For this to happen in the browser we need to install the LiveReload plugin one such implementation is Remote Live Reload for Chrome.

5. Global Settings

spring-boot-devtools provides a way to configure global settings that are not coupled with any application. This file is named as .spring-boot-devtools.properties and it located at $HOME.

6. Remote Applications

6.1. Remote Debugging via HTTP (Remote Debug Tunnel)

spring-boot-devtools provides out of the box remote debugging capabilities via HTTP, to have this feature it is required that spring-boot-devtools are packaged as part of the application. This can be achieved by disabling excludeDevtools configuration in the plugin in maven.

Here’s a quick sample:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <excludeDevtools>false</excludeDevtools>
            </configuration>
        </plugin>
    </plugins>
</build>

Now for remote debugging via HTTP to work, following steps have to be taken:

  1. An application being deployed and started on the server, should be started with Remote Debugging enabled:
    -Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n

    As we can see, the remote debugging port is not mentioned here. Hence, java will choose a random port

  2. For the same project, open the Launch configurations, choose the following options:
    Select main class: org.springframework.boot.devtools.RemoteSpringApplication
    In program arguments, add the URL for the application, e.g. http://localhost:8080
  3. Default port for debugger via spring-boot application is 8000 and can be overridden via:
    spring.devtools.remote.debug.local-port=8010
  4. Now create a remote-debug configuration, setting up the port as 8010 as configured via properties or 8000, if sticking to defaults

Here’s what the log will look like:

  .   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote ::  (v1.5.2.RELEASE)

2017-03-12 22:24:11.089  ...: Starting RemoteSpringApplication v1.5.2.RELEASE on machine with PID 10476 (..\org\springframework\boot\spring-boot-devtools\1.5.2.RELEASE\spring-boot-devtools-1.5.2.RELEASE.jar started by user in project)
2017-03-12 22:24:11.097  ...: No active profile set, falling back to default profiles: default
2017-03-12 22:24:11.357  ...: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11e21d0e: startup date [Sun Mar 12 22:24:11 IST 2017]; root of context hierarchy
2017-03-12 22:24:11.869  ...: The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2017-03-12 22:24:11.949  ...: LiveReload server is running on port 35729
2017-03-12 22:24:11.983  ...: Started RemoteSpringApplication in 1.24 seconds (JVM running for 1.802)
2017-03-12 22:24:34.324  ...: Remote debug connection opened

6.2. Remote Update

The remote client monitors the application classpath for changes as is done for remote restart feature. Any change in the classpath causes, the updated resource to be pushed to the remote application and a restart is triggered.

Changes are pushed when the remote client is up and running, as monitoring for changed files is only possible then.

Here’s what that looks like in the logs:

2017-03-12 22:33:11.613  INFO 1484 ...: Remote debug connection opened
2017-03-12 22:33:21.869  INFO 1484 ...: Uploaded 1 class resource

 7. Conclusion

With this quick article, we have just demonstrated how we can leverage the spring-boot-devtools module to make the developer experience better and reduce the development time by automating a lot of activities.

Introduction to Google Protocol Buffer

$
0
0

1. Overview

In this article, we’ll be looking at the Google Protocol Buffer (protobuf) – a well-known language-agnostic binary data format. We can define a file with a protocol and next, using that protocol, we can generate code in languages like Java, C++, C#, Go, or Python.

This is an introductory article to the format itself; if you want to see how to use the format with a Spring web application, have a look at this article.

2. Defining Maven Dependencies

To use protocol buffers is Java, we need to add a Maven dependency to a protobuf-java:

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>${protobuf.version}</version>
</dependency>

<properties>
    <protobuf.version>3.2.0</protobuf.version>
</properties>

3. Defining a Protocol

Let’s start with an example. We can define a very simple protocol in a protobuf format:

message Person {
    required string name = 1;
}

This is a protocol of a simple message of Person type that has only one required field – name that has a string type.

Let’s look at the more complex example of defining a protocol. Let’s say that we need to store person details in a protobuf format:

package protobuf;

package protobuf;

option java_package = "com.baeldung.protobuf";
option java_outer_classname = "AddressBookProtos";

message Person {
    required string name = 1;
    required int32 id = 2;
    optional string email = 3;

    repeated string numbers = 4;
}

message AddressBook {
    repeated Person people = 1;
}

Our protocol consists of two types of data: a Person and an AddressBook. After generating the code (more on this in the later section), those classes will be the inner classes inside the AddressBookProtos class.

When we want to define a field that is required – meaning that creating an object without such field will cause an Exception, we need to use a required keyword.

Creating a field with the optional keyword means that this field doesn’t need to be set. The repeated keyword is an array type of variable size.

All fields are indexed – the field that is denoted with number 1 will be saved as a first field in a binary file. Field marked with 2 will be saved next and so on. That gives us better control over how fields are laid out in the memory.

4. Generating Java Code From a Protobuf File

Once we define a file, we can generate code from it.

Firstly, we need to install protobuf on our machine. Once we do this, we can generate code by executing a protoc command:

protoc -I=. --java_out=. addressbook.proto

The protoc command will generate Java output file from our addressbook.proto file. The -I option specifies a directory in which a proto file resides. The java-out specifies a directory where the generated class will be created. 

Generated class will have setters, getters, constructors and builders for our defined messages. It will also have some util methods for saving protobuf files and deserializing them from binary format to Java class.

5. Creating an Instance of Protobuf Defined Messages

We can easily use a generated code to create Java instance of a Person class:

String email = "j@baeldung.com";
int id = new Random().nextInt();
String name = "Michael Program";
String number = "01234567890";
AddressBookProtos.Person person =
  AddressBookProtos.Person.newBuilder()
    .setId(id)
    .setName(name)
    .setEmail(email)
    .addNumbers(number)
    .build();

assertEquals(person.getEmail(), email);
assertEquals(person.getId(), id);
assertEquals(person.getName(), name);
assertEquals(person.getNumbers(0), number);

We can create a fluent builder by using a newBuilder() method on the desired message type. After setting up all required fields, we can call a build() method to create an instance of a Person class.

6. Serializing and Deserializing Protobuf 

Once we create an instance of our Person class, we want to save that on disc in a binary format that is compatible with a created protocol. Let’s say that we want to create an instance of the AddressBook class and add one person to that object.

Next, we want to save that file on disc – there is a writeTo() util method in auto-generated code that we can use:

AddressBookProtos.AddressBook addressBook 
  = AddressBookProtos.AddressBook.newBuilder().addPeople(person).build();
FileOutputStream fos = new FileOutputStream(filePath);
addressBook.writeTo(fos);

After executing that method, our object will be serialized to binary format and saved on disc. To load that data from a disc and deserialize it back to the AddressBook object we can use a mergeFrom() method:

AddressBookProtos.AddressBook deserialized
  = AddressBookProtos.AddressBook.newBuilder()
    .mergeFrom(new FileInputStream(filePath)).build();
 
assertEquals(deserialized.getPeople(0).getEmail(), email);
assertEquals(deserialized.getPeople(0).getId(), id);
assertEquals(deserialized.getPeople(0).getName(), name);
assertEquals(deserialized.getPeople(0).getNumbers(0), number);

7. Conclusion

In this quick article, we introduced a standard for describing and storing data in a binary format – Google Protocol Buffer.

We created a simple protocol, created Java instance that complies with defined protocol. Next, we saw how to serialize and deserialize objects using protobuf.

The implementation of all these examples and code snippets can be found in the GitHub project – this is a Maven project, so it should be easy to import and run as it is.

Introduction to Javatuples

$
0
0

1. Overview

A tuple is a collection of several elements that may or may not be related to each other. In other words, tuples can be considered anonymous objects.

For example, [“RAM”, 16, “Astra”] is a tuple containing three elements.

In this article, we will have a quick look at a really simple library that allows us to work with the tuple based data structures, named javatuples.

2. Built-in Javatuples Classes

This library provides us ten different classes that would suffice most of our requirements related to tuples:

  • Unit<A>
  • Pair<A,B>
  • Triplet<A,B,C>
  • Quartet<A,B,C,D>
  • Quintet<A,B,C,D,E>
  • Sextet<A,B,C,D,E,F>
  • Septet<A,B,C,D,E,F,G>
  • Octet<A,B,C,D,E,F,G,H>
  • Ennead<A,B,C,D,E,F,G,H,I>
  • Decade<A,B,C,D,E,F,G,H,I,J>

In addition to the classes above, there are two additional classes, KeyValue<A,B> and LabelValue<A,B>, which provide functionalities similar to Pair<A,B>, but differ in semantics.

As per the official siteall the classes in javatuples are typesafe and immutable. Each of the tuple class implements the IterableSerializable, and Comparable interface.

3. Adding Maven Dependency

Let’s add the Maven dependency to our pom.xml:

<dependency>
    <groupId>org.javatuples</groupId>
    <artifactId>javatuples</artifactId>
    <version>1.2</version>
</dependency>

Please check the Central Maven repository for the latest version.

4. Creating Tuples

Creating a tuple is really simple. We can use the corresponding constructors:

Pair<String, Integer> pair = new Pair<String, Integer>("A pair", 55);

There is also a little less verbose and semantically elegant way of creating a tuple:

Triplet<String, Integer, Double> triplet = Triplet.with("hello", 23, 1.2);

We can also create tuples from an Iterable:

List<String> listOfNames = Arrays.asList("john", "doe", "anne", "alex");
Quartet<String, String, String, String> quartet
  = Quartet.fromCollection(collectionOfNames);

Please note that the number of items in the collection should match the type of the tuple that we want to create. For example, we cannot create a Quintet using the above collection as it requires exactly five elements. Same is true for any other tuple class having a higher order than Quintet.

However, we can create a lower order tuple like Pair or a Triplet using the above collection, by specifying a starting index in the fromIterable() method:

Pair<String, String> pairFromList = Pair.fromIterable(listOfNames, 2);

The above code will result in creating a Pair containing “anne” and “alex“.

Tuples can be conveniently created from any array as well:

String[] names = new String[] {"john", "doe", "anne"};
Triplet<String, String, String> triplet2 = Triplet.fromArray(names);

5. Getting Values from Tuples

Every class in javatuples has a getValueX() method for getting the values from tuples, where X specifies the order of the element inside the tuple. Like the indexes in arrays, the value of X starts from zero.

Let’s create a new Quartet and fetch some values:

Quartet<String, Double, Integer, String> quartet 
  = Quartet.with("john", 72.5, 32, "1051 SW");

String name = quartet.getValue0();
Integer age = quartet.getValue2();
 
assertThat(name).isEqualTo("john");
assertThat(age).isEqualTo(32);

As we can see, the position of “john” is zero, “72.5” is one, and so on.

Note that the getValueX() methods are type-safe. That means, no casting is required.

An alternative to this is the getValue(int pos) method. It takes a zero-based position of the element to be fetched. This method is not type-safe and requires explicit casting:

Quartet<String, Double, Integer, String> quartet 
  = Quartet.with("john", 72.5, 32, "1051 SW");

String name = (String) quartet.getValue(0);
Integer age = (Integer) quartet.getValue(2);
 
assertThat(name).isEqualTo("john");
assertThat(age).isEqualTo(32);

Please note that the classes KeyValue and LabelValue have their corresponding methods getKey()/getValue() and getLabel()/getValue().

6. Setting Values to Tuples

Similar to getValueX(), all classes in javatuples have setAtX() methods. Again, X is zero-based positions for the element that we want to set:

Pair<String, Integer> john = Pair.with("john", 32);
Pair<String, Integer> alex = john.setAt0("alex");

assertThat(john.toString()).isNotEqualTo(alex.toString());

The important thing here is that the return type of setAtX() method is the tuple type itself. This is because the javatuples are immutable. Setting any new value will leave the original instance intact.

7. Adding and Removing Elements from Tuples

We can conveniently add new elements to the tuples. However, this will result in a new tuple of one order higher being created:

Pair<String, Integer> pair1 = Pair.with("john", 32);
Triplet<String, Integer, String> triplet1 = pair1.add("1051 SW");

assertThat(triplet1.contains("john"));
assertThat(triplet1.contains(32));
assertThat(triplet1.contains("1051 SW"));

It is clear from the above example that adding one element to a Pair will create a new Triplet. Similarly, adding one element to a Triplet will create a new Quartet.

The example above also demonstrates the use of contains() method provided by all the classes in javatuples. This is a really handy method for verifying if the tuple contains a given value.

It is also possible to add one tuple to another using the add() method:

Pair<String, Integer> pair1 = Pair.with("john", 32);
Pair<String, Integer> pair2 = Pair.with("alex", 45);
Quartet<String, Integer, String, Integer> quartet2 = pair1.add(pair2);

assertThat(quartet2.containsAll(pair1));
assertThat(quartet2.containsAll(pair2));

Note the use of containsAll() method. It will return true if all the elements of pair1 are present in quartet2.

By default, the add() method adds the element as a last element of the tuple. However, it is possible to add the element at a given position using addAtX() method, where X is the zero-based position where we want to add the element:

Pair<String, Integer> pair1 = Pair.with("john", 32);
Triplet<String, String, Integer> triplet2 = pair1.addAt1("1051 SW");

assertThat(triplet2.indexOf("john")).isEqualTo(0);
assertThat(triplet2.indexOf("1051 SW")).isEqualTo(1);
assertThat(triplet2.indexOf(32)).isEqualTo(2);

This example adds the String at position 1, which is then verified by the indexOf() method. Please note the difference in order of the types for the Pair<String, Integer> and the Triplet<String, String, Integer> after the call to addAt1() method call.

We can also add multiple elements using any of add() or addAtX() methods:

Pair<String, Integer> pair1 = Pair.with("john", 32);
Quartet<String, Integer, String, Integer> quartet1 = pair1.add("alex", 45);

assertThat(quartet1.containsAll("alex", "john", 32, 45));

In order to remove an element from the tuple, we can use the removeFromX() method. Again, X specifies the zero-based position of the element to be removed:

Pair<String, Integer> pair1 = Pair.with("john", 32);
Unit<Integer> unit = pair1.removeFrom0();

assertThat(unit.contains(32));

8. Converting Tuples to List/Array

We have already seen how to convert a List to a tuple. Let’s now see hot to convert a tuple to a List:

Quartet<String, Double, Integer, String> quartet
  = Quartet.with("john", 72.5, 32, "1051 SW");
List<Object> list = quartet.toList();

assertThat(list.size()).isEqualTo(4);

It is fairly simple. The only thing to note here is that we will always get a List<Object>, even if the tuple contains the same type of elements.

Finally, let’s convert the tuple to an array:

Quartet<String, Double, Integer, String> quartet
  = Quartet.with("john", 72.5, 32, "1051 SW");
Object[] array = quartet.toArray();

assertThat(array.length).isEqualTo(4);

Clear enough, the toArray() method always returns an Object[].

9. Conclusion

In this article, we have explored the javatuples library and observed it’s simplicity. It provides elegant semantics and is really easy to use.

Make sure you check out the complete source code for this article over on GitHub. The complete source code contains a little more examples than the ones covered here. After reading this article, the additional examples should be easy enough to understand.

Introduction to Javassist

$
0
0

1. Overview

In this article, we will be looking at the Javasisst (Java Programming Assistant) library.

Simply put, this library makes the process of manipulating Java bytecode simpler by using a high-level API than the one in the JDK.

2. Maven Dependency

To add the Javassist library to our project we need to add javassist into our pom:

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>${javaassist.version}</version>
</dependency>

<properties>
    <javaassist.version>3.21.0-GA</javaassist.version>
</properties>

3. What is the Bytecode?

At a very high level, every Java class that is written in a plain text format and compiled to bytecode – an instruction set that can be processed by the Java Virtual Machine. The JVM translates bytecode instructions into machine level assembly instructions.

Let’s say that we have a Point class:

public class Point {
    private int x;
    private int y;

    public void move(int x, int y) {
        this.x = x;
        this.y = y;
    }

    // standard constructors/getters/setters
}

After compilation, the Point.class file containing the bytecode will be created. We can see the bytecode of that class by executing the javap command:

javap -c Point.class

This will print the following output:

public class com.baeldung.javasisst.Point {
  public com.baeldung.javasisst.Point(int, int);
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: iload_1
       6: putfield      #2                  // Field x:I
       9: aload_0
      10: iload_2
      11: putfield      #3                  // Field y:I
      14: return

  public void move(int, int);
    Code:
       0: aload_0
       1: iload_1
       2: putfield      #2                  // Field x:I
       5: aload_0
       6: iload_2
       7: putfield      #3                  // Field y:I
      10: return
}

All those instructions are specified by the Java language; a large number of them are available.

Let’s analyze the bytecode instructions of the move() method:

  • aload_0 instruction is loading a reference onto the stack from the local variable 0
  • iload_1 is loading an int value from the local variable 1
  • putfield is setting a field x of our object. All operations are analogical for field y
  • The last instruction is a return

Every line of Java code is compiled to bytecode with proper instructions. The Javassist library makes manipulating that bytecode relatively easy.

4. Generating a Java Class

Javassist library can be used for generating new Java class files.

Let’s say that we want to generate a JavassistGeneratedClass class that implements a java.lang.Cloneable interface. We want that class to have an id field of int typeThe ClassFile is used to create a new class file and FieldInfo is used to add a new field to a class:

ClassFile cf = new ClassFile(
  false, "com.baeldung.JavassistGeneratedClass", null);
cf.setInterfaces(new String[] {"java.lang.Cloneable"});

FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I");
f.setAccessFlags(AccessFlag.PUBLIC);
cf.addField(f);

After we create a JavassistGeneratedClass.class we can assert that it actually has an id field:

ClassPool classPool = ClassPool.getDefault();
Field[] fields = classPool.makeClass(cf).toClass().getFields();
 
assertEquals(fields[0].getName(), "id");

5. Loading Bytecode Instructions of Class

If we want to load bytecode instructions of an already existing class method, we can get a CodeAttribute of a specific method of the class. Then we can get a CodeIterator to iterate over all bytecode instructions of that method.

Let’s load all bytecode instructions of the move() method of the Point class:

ClassPool cp = ClassPool.getDefault();
ClassFile cf = cp.get("com.baeldung.javasisst.Point")
  .getClassFile();
MethodInfo minfo = cf.getMethod("move");
CodeAttribute ca = minfo.getCodeAttribute();
CodeIterator ci = ca.iterator();

List<String> operations = new LinkedList<>();
while (ci.hasNext()) {
    int index = ci.next();
    int op = ci.byteAt(index);
    operations.add(Mnemonic.OPCODE[op]);
}

assertEquals(operations,
  Arrays.asList(
  "aload_0", 
  "iload_1", 
  "putfield", 
  "aload_0", 
  "iload_2",  
  "putfield", 
  "return"));

We can see all bytecode instructions of the move() method by aggregating bytecodes to the list of operations, as shown in the assertion above.

6. Adding Fields to Existing Class Bytecode

Let’s say that we want to add a field of int type to the bytecode of the existing class. We can load that class using ClassPoll and add a field into it:

ClassFile cf = ClassPool.getDefault()
  .get("com.baeldung.javasisst.Point").getClassFile();

FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I");
f.setAccessFlags(AccessFlag.PUBLIC);
cf.addField(f);

We can use reflection to verify that id field exists on the Point class:

ClassPool classPool = ClassPool.getDefault();
Field[] fields = classPool.makeClass(cf).toClass().getFields();
List<String> fieldsList = Stream.of(fields)
  .map(Field::getName)
  .collect(Collectors.toList());
 
assertTrue(fieldsList.contains("id"));

7. Adding Constructor to Class Bytecode

We can add a constructor to the existing class mentioned in one of the previous examples by using an addInvokespecial() method.

And we can add a parameterless constructor by invoking a <init> method from java.lang.Object class:

ClassFile cf = ClassPool.getDefault()
  .get("com.baeldung.javasisst.Point").getClassFile();
Bytecode code = new Bytecode(cf.getConstPool());
code.addAload(0);
code.addInvokespecial("java/lang/Object", MethodInfo.nameInit, "()V");
code.addReturn(null);

MethodInfo minfo = new MethodInfo(
  cf.getConstPool(), MethodInfo.nameInit, "()V");
minfo.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(minfo);

We can check for the presence of the newly created constructor by iterating over bytecode:

CodeIterator ci = code.toCodeAttribute().iterator();
List<String> operations = new LinkedList<>();
while (ci.hasNext()) {
    int index = ci.next();
    int op = ci.byteAt(index);
    operations.add(Mnemonic.OPCODE[op]);
}

assertEquals(operations,
  Arrays.asList("aload_0", "invokespecial", "return"));

8. Conclusion

In this article, we introduced the Javassist library, with the goal of making bytecode manipulation easier.

We focused on the core features and generated a class file from Java code; we also made some bytecode manipulation of an already created Java class.

The implementation of all these examples and code snippets can be found in the GitHub project – this is a Maven project, so it should be easy to import and run as it is.

Java Web Weekly, Issue 168

$
0
0

Lots of interesting writeups on Java 9 this week.

Here we go…

1. Spring and Java

>> Troubleshooting Memory Issues in Java Applications [infoq.com]

Fixing memory issues can be challenging. This comprehensive guide will give you an idea where to start looking for when you encounter them.

>> Pipeline as code with a Spring Boot application [pragmaticintegrator.wordpress.com]

“Infrastructure as Code” is not a new approach, but definitely still very interesting for the significant advantages and maturity it brings.

>> JSR 269 Maintenance Review for Java SE 9 [oracle.com]

A few updates regarding Pluggable Annotation Processing API for Java SE 9.

>> An update on GlassFish 5 [oracle.com]

The first promoted build of GF5 was released recently.

>> Spring Boot and hypermedia, part 1: HAL [insaneprogramming.be]

A short guide to building a self-discoverable API with Spring Boot.

>> Types Are Mightier Than Tests [sitepoint.com]

TDD is a powerful and necessary tool, although sometimes a weak one when it comes to checking the correctness of imperative programs. Higher abstractions coupled with strong type system can make your life easier by decreasing the number of spots where mistakes can even be made.

>> Coping with stringly-typed [frankel.ch]

In the world of strong static typing, sometimes it’s easy to abuse String type. There are some solutions to dealing with such situations.

>> 5 new features in Hibernate 5 every developer should know [thoughts-on-java.org]

There are a few new interesting features in the newest Hibernate release.

Also worth reading:

Webinars and presentations:

Time to upgrade:

2. Technical

>> Kotlin 1.1 Adds Coroutines, Type Aliases, Improved JavaScript Support [infoq.com]

Looks like Kotlin is getting even more very interesting features. I am definitely curious how this one will develop over time.

>> SelfEncapsulation [martinfowler.com]

An interesting approach where you restrict yourself to using getters/setters when possible instead of accessing fields directly. This can make refactoring much easier if some additional non-standard logic needs to be performed when accessing fields.

>> Protecting Sensitive Data [techblog.bozho.net]

A few tips for increasing security of your highly sensitive data.

>> Is An Agile Java Standard Possible? [sitepoint.com]

And some interesting thoughts about the state of the Java platform development. It turns out that making the whole process Agile, might be not that easy.

Also worth reading:

3. Musings

>> Programmer Career Planning [henrikwarne.com]

Sometimes it’s worth leaving the comfort zone in order to learn something new and to increase your position in the market.

>> Password Rules Are Bullshit [codinghorror.com]

Strict password policies can be irritating especially when your randomly generated password does not match all required criteria 🙂

>> The Case for a Team Standard [daedtech.com]

It’s important to make sure that your standards not only exist but are also high.

Also worth reading:

4. Comics

And my favorite Dilberts of the week:

>> I can’t feel my legs [dilbert.com]

>> The vision was the hard part [dilbert.com]

>> I like everything you said expect the “we” part [dilbert.com]

5. Pick of the Week

>> Humans are born irrational, and that has made us better decision-makers [qz.com]

Viewing all 3692 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>