Česky   |  Deutsch   |  English   |  Español   |  Français   |  Indonesia   |  日本語   |  한글   |  Polski   |  Português (BR)   |  Türkçe   |  中文   |  正體中文   |  Your Language  
PlanetNetbeans
Planet NetBeans is an aggregation of NetBeans related musings from all over the Blogosphere.
Adam Bien - January 16, 2018 11:37 AM
Metrics, ServerSockets, SSE, WebSockets, Smelling DAOs, JPA Historization, SLSB scalability, Killing EJBs, Logging, ELK, Docker, Kubernetes, Openshift, Licensing, Obfuscation -- or 46th airhacks.tv

This time "Metrics, ServerSockets, SSE, WebSockets, Homework / Code Review of a basic CRUD, Smelling DAOs, JPA Historisation, SLSB design for scalability, Killing EJBs, Logging, ELK, Docker, Kubernetes, Openshift, Licensing, Obfuscation" were discussed.

Any questions left? Ask now: https://gist.github.com/AdamBien/dce90e8d7162c06ca3395f9a9ceb7bf1 and get the answers at the next airhacks.tv.

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.
Real World Java EE Workshops [Airport Munich]>

Adam Bien - January 15, 2018 05:41 AM
Web Components On-Demand Workshops

After covering the "basics" in WebStandards igniter, now 50+ episodes of continuous Web Components (Custom Elements, Shadow DOM, CSS 3 styling, Templates, ES 6 imports) coding workshop is available: webcomponents.training. No installation, no dependencies, no builds: only vanilla web (browser) standards, without any external frameworks or dependencies, were used.

Are you already building, or still migrating? Learn once, apply anywhere :-):

Web Components from AdamBien on Vimeo.

See you also at: PWAs / SPAs with Web Components Workshop at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting.
Real World Java EE Workshops [Airport Munich]>

Adam Bien - January 11, 2018 08:34 AM
Pipeline-specific timeouts with CompletableFuture#orTimeout and JAX-RS 2.1

CompletableFuture#orTimeout (>= Java 9) method

"...exceptionally completes this CompletableFuture with a TimeoutException if not otherwise completed before the given timeout. ..."
and is therefore well suited to set a pipeline-specific timeout.

The method AsyncResponse#setTimeout sets the max timeout per request:


import static java.util.concurrent.CompletableFuture.supplyAsync;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.Response;

@Path("ping")
public class PingResource {

    @GET
    public void ping(@Suspended AsyncResponse response) {
        response.setTimeout(1, TimeUnit.SECONDS); //global timeout
        supplyAsync(this::answer).
                thenAccept(response::resume).
                orTimeout(100, TimeUnit.MILLISECONDS). //pipeline specific timeout
                exceptionally((t) -> handleTimeout(response::resume, t));
    }

    Void handleTimeout(Consumer<Response> consumer, Throwable t) {
        consumer.accept(Response.status(503).
                header("cause", "timeout in the pipeline").
                header("exception", t.toString()).
                build());
        return null;
    }

    public String answer() {
        try {
            Thread.sleep(200);
            return "42 + " + System.currentTimeMillis();
        } catch (InterruptedException ex) {
            throw new IllegalStateException("cannot sleep");
        }
    }
}

The request: curl -i http://localhost:8080/completable-timeout/resources/ping returns:


HTTP/1.1 503 Service Unavailable
X-Powered-By: Servlet/4.0
cause: timeout in the pipeline
exception: java.util.concurrent.TimeoutException
(...)

See you at Java EE 8 / Java 9 / Web Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.
Real World Java EE Workshops [Airport Munich]>

Adam Bien - January 10, 2018 08:49 AM
Java 9's StackWalker

The Java 9's StackWalker class allows stack walking without instantiating an Exception.

The following unit test:


package com.airhacks;

import java.lang.StackWalker.StackFrame;
import org.junit.Before;
import org.junit.Test;

public class StackWalkerBasicsTest {

    private StackWalker walker;

    @Before
    public void init() {
        this.walker = StackWalker.getInstance();
    }

    @Test
    public void walkTheStack() {
        this.walker.forEach(this::print);
    }

    void print(StackFrame frame) {
        String className = frame.getClassName();
        String methodName = frame.getMethodName();
        int lineNumber = frame.getLineNumber();
        System.out.println(className + "." + methodName + ":" + lineNumber);
    }
}

Writes the following output:


com.airhacks.StackWalkerBasicsTest.walkTheStack:24
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall:50
org.junit.internal.runners.model.ReflectiveCallable.run:12
org.junit.runners.model.FrameworkMethod.invokeExplosively:47
org.junit.internal.runners.statements.InvokeMethod.evaluate:17
org.junit.internal.runners.statements.RunBefores.evaluate:26
org.junit.runners.ParentRunner.runLeaf:325
org.junit.runners.BlockJUnit4ClassRunner.runChild:78
org.junit.runners.BlockJUnit4ClassRunner.runChild:57
org.junit.runners.ParentRunner$3.run:290
org.junit.runners.ParentRunner$1.schedule:71
org.junit.runners.ParentRunner.runChildren:288
org.junit.runners.ParentRunner.access$000:58
org.junit.runners.ParentRunner$2.evaluate:268
org.junit.runners.ParentRunner.run:363
org.apache.maven.surefire.junit4.JUnit4Provider.execute:252
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet:141
org.apache.maven.surefire.junit4.JUnit4Provider.invoke:112
org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray:189
org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke:165
org.apache.maven.surefire.booter.ProviderFactory.invokeProvider:85
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess:115
org.apache.maven.surefire.booter.ForkedBooter.main:75    

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.
Real World Java EE Workshops [Airport Munich]>

Adam Bien - January 09, 2018 10:21 AM
Building a Web Component with Java EE 8 Backend

In this screencast I created a Java EE 8 application with JAX-RS endpoint and JSON-B serialization from scratch, then developed a Custom Element (part of the Web Components specification) which talks to the Java EE 8 backend in 6 mins. No external dependencies were used in frontend and backend.


Real World Java EE Workshops [Airport Munich]>

Adam Bien - January 08, 2018 10:16 AM
Homework Review, JPA history, Business Metrics, Sanity, WebSockets, SSE, XMPP, Logging, Licensing or Questions for the 46th airhacks.tv

Questions for the 46th airhacks.tv:

  1. Surprise
  2. Interactive review of a CRUD homework assignment
  3. JPA history
  4. Testing and embedded integration tests
  5. Getting rid of EJBs
  6. Business metrics with Java EE
  7. THE DAOs smell and Deltaspike Data
  8. Asynchronous JAX-RS resource
  9. Docker swarm vs. kubernetes vs. openshift
  10. SLSB command pattern vs. one bean with multiple methods
  11. How to stay sane (sanity is subjective :-)
  12. Server Push: WebSockets vs. SSE
  13. ServerSocket handling with Java EE -- or how to XMPP with Java EE
  14. Logging with java.util.logging and what about ELK?
  15. Java EE and obfuscation
  16. Licensing Java EE applications
  17. The Pair class and Apache Commons

Any questions left? Ask now: or wait a month.

Ask questions during the show via twitter mentioning me: http://twitter.com/AdamBien (@AdamBien) or using the hashtag: #airhacks. You can join the Q&A session live each first Monday of month, 6 P.M at airhacks.tv or http://www.ustream.tv/channel/adambien


Real World Java EE Workshops [Airport Munich]>

DukeScript - December 24, 2017 05:53 AM
iOS with Multi OS Engine

Christmas 2017 is here and a new version of DukeScript archetypes brings a new way to launch your application on iOS.

Version 0.20 gives you support for Multi OS Engine!

How hard is it to try? Easy, fairly easy. First of all use one of the Maven archetypes to create and build your project:

$ mvn archetype:generate \
  -DarchetypeGroupId=com.dukescript.archetype \
  -DarchetypeArtifactId=knockout4j-archetype \
  -DarchetypeVersion=0.20 \
  -Dmoepath=client-ios \
  -DartifactId=moetest \
  -DgroupId=com.acme.demo \
  -Dversion=1.0-SNAPSHOT
$ cd moetest
$ mvn install

Assuming the Maven build has succeeded, you are ready to execute your project. To do that, you have to select proper target device. You can use moe:listSimulators command of the client-ios subproject. For example, if you are interested in iPhone X, use:

$ mvn -f client-ios/pom.xml moe:listSimulators | grep iPhone.X

The ID of your iPhone X simulator gets printed and you can perform the final step. Launch your application in an iOS simulator:

$ mvn -f client-ios/pom.xml moe:launch -Dmoe.launch.simulatorId=_theSelectedID_

Heuréka. Your application is running:

XCode

After performing the above steps you may feel like a master of the Maven command line interface! However sometimes it is more convenient to use an IDE. As such the DukeScript archetype for Multi OS Engine also comes with support for XCode:

$ open client-ios/xcode/ios.xcodeproj/

In the XCode interface you can configure the deployment options of your application in the traditional XCode way. You can execute your application in the simulator as well as on the device:

Enjoy the new support for Multi OS Engine. Read more about the standard structure of the archetypes in our introduction tutorial. If some detail isn’t clear yet, don’t hesitate checking our getting started guide. Alternatively consider reading the Java Everywhere book.

Merry Christmas and Happy New Year!

Adam Bien - December 21, 2017 02:18 PM
Reactive JAX-RS 2.1 Client Combined with Asynchronous Resource and CompletableFuture

The reactive JAX-RS 2.1 client integrates seamlessly with asynchronous JAX-RS resources and Java 8+CompletableFuture:

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


Real World Java EE Workshops [Airport Munich]>

APIDesign - Blogs - December 18, 2017 11:46 AM
Is Spring the Sole Reason why Java is Becoming the new COBOL?

Is there anything good on Spring that wouldn't be seen ridiculous by non-enterprise-Java users?

--JaroslavTulach 11:46, 18 December 2017 (UTC)

Adam Bien - December 17, 2017 01:11 PM
4th airhacks.fm Episode: "Micro Java EE"

4th episode "Micro Java EE" of airhacks.fm podcast with special guest, Payara CEO, Steve Millidge is available. We discussed Microservices, Cloud Native Java EE, Microprofile, EE4J, Thin WARs, Ueber JARS and Fat JARs.

Subscribe to airhacks.fm podcast via: RSS iTunes


Real World Java EE Workshops [Airport Munich]>

Adam Bien - December 08, 2017 05:20 AM
From BeanShell and Kotlin over Deadlocked Conversations to AWS, Authentication and Java PWAs -- 45th airhacks.tv is available

From BeanShell over deadlocked conversations to AWS and authentication. The 45th airhacks.tv is available:

Any questions left? Ask now: https://gist.github.com/AdamBien/725f0e529bda54e2a35cf35c88f49c26 and get the answers at the next airhacks.tv.

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.
Real World Java EE Workshops [Airport Munich]>

Adam Bien - December 07, 2017 07:57 AM
Serializing and Deserializing a POJO with LocalDate into JSON using JSON-B and Java EE 8

To serialize a POJO with JSON-B from Java EE 8 containing a java.time.LocalDate, you can either use the default format, or specify the serialization format with @JsonbDateFormat annotation:


import java.time.LocalDate;
import javax.json.bind.annotation.JsonbCreator;
import javax.json.bind.annotation.JsonbDateFormat;
import javax.json.bind.annotation.JsonbProperty;

public class Developer {

    public LocalDateTime birthdate;

    @JsonbDateFormat(value = "yyyy-MM-dd")
    public LocalDate firstHack;

    @JsonbCreator
    public Developer(
            @JsonbProperty("birthdate") LocalDateTime birthdate, 
            @JsonbProperty("firstHack") LocalDate firstHack) {
        this.birthdate = birthdate;
        this.firstHack = firstHack;
    }
}

Now the Developer can be serialized and deserialized with a javax.json.bind.Jsonb instance:


import java.time.LocalDate;
import java.time.Month;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;

public class DateSerializationTest {
    
    private Jsonb jsonb;
    
    @Before
    public void init() {
        this.jsonb = JsonbBuilder.
        newBuilder().
        build();
    }

    @Test
    public void serialize() {
        Developer developer = new Developer(LocalDateTime.of(1995, Month.MARCH, 12, 12, 42), 
                LocalDate.of(1998, Month.MARCH, 12));
        String serialized = this.jsonb.toJson(developer);
        System.out.println("serialized = " + serialized);
        assertThat(serialized, containsString("birthdate"));

    }

    @Test
    public void deserialize() {
        String deserialzed = " {\"birthdate\":\"1995-03-12T12:42:00\",\"firstHack\":\"1998-03-12\"}";
        Developer duke = this.jsonb.fromJson(deserialzed, Developer.class);
        assertThat(duke.birthdate.getYear(), is(1995));
    }

}

To run the example as JUnit test, you will need the following dependencies:


<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.1</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.eclipse</groupId>
    <artifactId>yasson</artifactId>
    <version>1.0</version>
    <scope>runtime</scope>
</dependency>

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


Real World Java EE Workshops [Airport Munich]>

Adam Bien - December 06, 2017 08:11 AM
EM switching, BeanShell, Kotlin, JPA and JDBC, AWS, Authentication, XA, PWAs, SPAs and Java, JSON-B or the last airhacks.tv in 2017

Questions for the 45th, and very last, airhacks.tv show in 2017:

  1. About BeanShell
  2. Header parameters behind apache
  3. Switching between persistence units / EntityManager
  4. Thoughts on Kotlin
  5. Deadlocked conversations
  6. JPA and JDBC pooling
  7. Which AWS instance to take?
  8. Upgrading GlassFish without downtime
  9. Java EE 8 authentication and redirect / forward
  10. Dealing with complex components like tables in the "No Dependencies, Java EE-like" web development
  11. How to handle database connections in the clouds
  12. Two DBs with or without XA
  13. Java's answer to PWAs and SPAs
  14. CompletableFuture, JAX-RS and exception handling
  15. Form authentication and encryption
  16. JSON-B and LocalDateTime mapping
  17. JAX-WS, connection timeout, transaction timeout and dealing with rollbacks

Any questions left? Ask now, or wait a year.

Ask questions during the show via twitter mentioning me: http://twitter.com/AdamBien (@AdamBien) or using the hashtag: #airhacks or the live chat: http://www.ustream.tv/channel/adambien

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.
Real World Java EE Workshops [Airport Munich]>

Adam Bien - December 05, 2017 06:30 AM
Monitoring Java EE Appservers with Prometheus and Grafana

Monitoring und visualising built-in Java EE metrics (payara.fish) with prometheus, grafana and a little help of a 16kB side car firehose:

See you at Java EE Microservices. Is Munich's airport too far? Learn from home: javaeemicro.services and Java EE Performance, Monitoring and Troubleshooting


Real World Java EE Workshops [Airport Munich]>

Adam Bien - December 04, 2017 05:03 AM
Java EE 8 on Java 9 - From Install to Deployment with OpenLiberty Server

Download, install, configure openliberty.io and deploy a sample Java EE 8 application with Java 9 features under 10 minutes with Maven:

See you at Java EE 8 on Java 9, at Munich Airport, Terminal 2
Real World Java EE Workshops [Airport Munich]>

Adam Bien - December 03, 2017 10:47 AM
Using Java 9 HTTP Client with JUnit and Maven

Java 9 comes with built-in HTTP (2) client (incubator status):


import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.time.Duration;
import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;

public class HttpClientTest {

    private HttpClient client;

    @Before
    public void init() {
        this.client = HttpClient.newHttpClient();
    }

    @Test
    public void get() throws IOException, InterruptedException {
        URI uri = URI.create("http://airhacks.com");
        HttpRequest getRequest = HttpRequest.newBuilder(uri).
                GET().
                timeout(Duration.ofMillis(500)).
                build();
        HttpResponse<String> response = this.client.send(getRequest,
                HttpResponse.BodyHandler.asString(Charset.defaultCharset()));
        String payload = response.body();
        assertThat(payload, containsString("java"));
    }
}

The HTTP client resides in jdk.incubator.httpclient module and has to be "required". The module-info.java resides in src/main/java:

module com.airhacks.http {
    requires jdk.incubator.httpclient;
}

You will need the maven-compiler-plugin at least in the version > 3.6.1


<build>
<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
    </plugin>
</plugins>
</build>    

Now the unit tests compiles, but the execution fails with:


java.lang.NoClassDefFoundError: Ljdk/incubator/http/HttpClient;
    at java.base/java.lang.Class.getDeclaredFields0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3024)
    at java.base/java.lang.Class.getDeclaredFields(Class.java:2205)    

Although the module is declared, it has to be still added with the following JVM argument:


<properties>
    <argLine>--add-modules jdk.incubator.httpclient</argLine>
(...)
</properties>
See you at Java EE 8 on Java 9, at Munich Airport, Terminal 2
Real World Java EE Workshops [Airport Munich]>

Adam Bien - December 02, 2017 06:20 AM
Time travelling with Bean Validation 2.0 and Java EE 8

With Java EE 8 and Bean Validation 2.0 JSR-380 you can time travel by passing an adjusted java.time.Clock instance to the clockProvider method:


import java.time.Clock;
import java.time.Duration;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
(...)

public class BeanValidationTest {

private Validator validator;

@Before
public void init() {
    ValidatorFactory factory = Validation
            .byDefaultProvider()
            .configure()
            .clockProvider(this::configureClockWithFutureTime)
            .buildValidatorFactory();
    this.validator = factory.getValidator();
}

Clock configureClockWithFutureTime() {
    return Clock.offset(Clock.systemDefaultZone(), Duration.ofSeconds(10));
}


Now you can configure whether your vacations are already over:

        
import java.util.Date;
import javax.validation.constraints.PastOrPresent;

public class Vacations {

    @PastOrPresent
    private Date date;

    public Vacations() {
        this.date = new Date();
    }
}


@Test
public void vacationsAreOver() {
    Set<ConstraintViolation<Vacations>> violations = this.validator.validate(new Vacations());
    assertTrue(violations.isEmpty());
}

...or whether you have to work again:


import java.util.Date;
import javax.validation.constraints.Future;

public class Development {

    @Future
    private Date date;
    public Development() {
        this.date = new Date();
    }
}
//....
@Test
public void weAreWorkingNow() {
    Set<ConstraintViolation<Development>> violations = this.validator.validate(new Development());
    boolean rightMessage = violations.stream().
            map(violation -> violation.getMessage()).
            allMatch(message -> "must be a future date".equalsIgnoreCase(message));
    assertTrue(rightMessage);
    assertFalse(violations.isEmpty());
}

}

To run the bean validation as a JUnit test, you will need the following dependencies:


<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.5.Final</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.el</artifactId>
    <version>3.0.0</version>
    <scope>test</scope>
</dependency>

See you at Java EE 8 on Java 9, at Munich Airport, Terminal 2


Real World Java EE Workshops [Airport Munich]>

Adam Bien - December 01, 2017 08:17 AM
Java 9 orTimeout and JAX-RS AsyncResponse

Java 9 introduced the CompletableFuture#orTimeout method which allows the configuration of a "per pipeline" timeout. In case there are multpiple pipelines involved to answer a single request, the JAX-RS AsyncResponse#setTimeout method can be used to set the max duration (see it in action: javaeemicro.services) for the entire request:


import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.Response;

@Path("ping")
public class PingResource {

    @GET
    public void ping(@Suspended AsyncResponse response) {

        CompletableFuture.supplyAsync(this::answer).
                thenAccept(response::resume).
                orTimeout(100, TimeUnit.MILLISECONDS).
                exceptionally((t) -> handleTimeout(response::resume, t));


    }

    Void handleTimeout(Consumer<Response> consumer, Throwable t) {
        consumer.accept(Response.status(503).
                header("cause", "timeout in the pipeline").
                header("exception", t.toString()).
                build());
        return null;
    }

    public String answer() {
        try {
            Thread.sleep(200);
            return "42 + " + System.currentTimeMillis();
        } catch (InterruptedException ex) {
            throw new IllegalStateException("cannot sleep");
        }
    }
}    

The request: curl -i [...]/ping outputs:


HTTP/1.1 503 Service Unavailable
X-Powered-By: Servlet/4.0
cause: timeout in the pipeline
exception: java.util.concurrent.TimeoutException
Date: Fri, 01 Dec 2017 06:25:32 GMT
Content-Length: 0
Content-Language: en-DE
Connection: Close

See you at Java EE 8 on Java 9, at Munich Airport, Terminal 2
Real World Java EE Workshops [Airport Munich]>

Adam Bien - November 30, 2017 06:27 AM
From JDK 1.0 over CORBA, RPC, REST over Java EE to Cloudnative and Back

From early Java (JDK 1.0), over CORBA, serverside Java, WebSphere, openliberty.io, heavyweight J2EE and lightweight Java EE and back. About the meaning of "cloudnative" and why footprint and size matter.

A conversation with an ebullient hacker ebullientworks / @ebullientworks: subscribe to airhacks.fm podcast via: RSS or iTunes


Real World Java EE Workshops [Airport Munich]>

Adam Bien - November 29, 2017 11:54 AM
Receiving Server Sent Events (SSE) with JAX-RS 2.1 and Java EE 8

To receive Server Sent Events (SSE) with a Java JAX-RS 2.1 (Java EE 8) client you will need an additional dependency:


<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-sse</artifactId>
    <version>2.26</version>
</dependency>

For the initialization of a SseEventSource you need a WebTarget which comes from a "stock" JAX-RS client:


import static java.util.concurrent.TimeUnit.SECONDS;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.sse.InboundSseEvent;
import javax.ws.rs.sse.SseEventSource;

public class SSEClientIT {

    private Client client;
    private WebTarget tut;

    @Before
    public void initClient() {
        this.client = ClientBuilder.newClient();
        this.tut = this.client.target("http://localhost:8080/sse/resources/beats");
    }
...with the target you can create a SseEventSource to register an instance of: Consumer<InboundSseEvent> as listener:

    @Test
    public void init() throws IOException {
        SseEventSource sse = SseEventSource.
            target(this.tut)
                .reconnectingEvery(2, SECONDS)
                .build();
        sse.register(this::onMessage);
        sse.open();
        
        //block here, otherwise the test method will complete
    }

    void onMessage(InboundSseEvent event) {
        String id = event.getId();
        String name = event.getName();
        String payload = event.readData();
        String comment = event.getComment();
        //processing...
    }

}
See you at Java EE 8 on Java 9, at Munich Airport, Terminal 2
Real World Java EE Workshops [Airport Munich]>

Adam Bien - November 28, 2017 05:37 AM
JSF 2.3 and HTTP/2

JSF 2.3 from Java EE 8 comes with HTTP/2 push support out-of-the-box. In this 3 minute video I created a calendar component and inspected the network traffic:

See you at Java EE 8 on Java 9, at Munich Airport, Terminal 2
Real World Java EE Workshops [Airport Munich]>

Adam Bien - November 27, 2017 05:15 AM
End Of Year 2017 Developer Events

Subscribe to airhacks.fm podcast via: iTunes


Real World Java EE Workshops [Airport Munich]>

NetBeans – Enrico Scantamburlo - November 26, 2017 09:20 PM
XML DOM parsing in Groovy

These days I had to modify several XML files at once, I took this chance to use Groovy and to learn something new.  I put an example project on GitHub.

Gradle project creation

I decided to create a Gradle project, NetBeans supports it via an external plugin, but I created it using the command line

mkdir groovyDom
cd groovyDom
gradle init --type groovy-application
gradle build
gradle run

with these commands, a project is created and run, the first time it takes some time because it has to download Gradle.

Spok test framework

I used an XML file from Microsoft to create my examples, they are written as tests using the Spok framework. The Spok framework is the way you write test in Groovy, I found it very straightforward to learn and very expressive

A test class called AppTest was created automatically by Gradle; inside you can define methods like:

def "File exists"() {
setup: // Initialization
ClassLoader classLoader = getClass().getClassLoader();

when: // Do something
// The file is inside /src/test/resources
File file = new File(classLoader.getResource("test.xml").getFile());

then: // Condition
file.isFile()
}

after the then: keyword is possible to combine more conditions using the and: keyword. I used this feature a lot to test multiple conditions.

There is also a dedicated folder for test resources, src/test/resources, I put my XML file there so I could load it easily.

 

Navigating the DOM

Back to the DOM, loading the model requires fewer lines of code thanks to Groovy:

def document
file.withReader{ reader ->
    document = DOMBuilder.newInstance().parse(reader) 
}

Groovy re-uses the Java APIs to parse the dom, but enhanced with the Pimp My Library pattern. This pattern allows to add methods to classes without extending them, as far as I remember is available also in Scala and C#.

I searched nodes and attributes using xpath, this is not a feature of the normal Java API but it was injected by Groovy using the aforementioned Pimp My Library pattern. The code must be enclosed in a use section like:

use (DOMCategory){ //Pimp my library pattern
 // I can search with the xpath syntax
 computerBooks = document.xpath("/catalog/book[genre='Computer']", NODESET)
 
 titles = computerBooks.collect{ book ->
 
 book.title.text()
 
 } as ArrayList
 
 } 

The NODESET parameter means that the result will be a collection of DOM nodes, we can create another collection from this one using the standard Groovy syntax and extract the text content of the node with the text() method.

One of the nicest aspects of Groovy is that it can create methods and fields on the fly, in this case, if we have an element called “book” and a sub-element called “title” we can access the content of the title like book.title.text() .

Without using xpath, I could have just navigated through the nodes from the root element, that is retrieved as:

def catalog = document.documentElement

Reading and writing attributes

There is an easy way to read attributes values using a syntax like computerBooks.item(0).’@id’, in this case, I extract the Id attribute from the first element of computerBooks.

I found no way to set an attribute but using the original Java method, setAttribute().

    computerBooks.item(0).'@id'

Header Designed by Freepik

Adam Bien - November 26, 2017 11:26 AM
Monitoring Payara / Glassfish with Prometheus

Firehose v0.0.3 supports "extractor" scripts (Nashorn's implementation of Java's java.util.function.Function interface) which can be used for extraction of arbitrary monitoring sources. e.g. to convert GlassFish's / Payara's the "Average request processing time" metric: curl http://localhost:4848/monitoring/domain/server/http-service/server/request/processingtime.json available under JSON:

{"message":"","command":"Monitoring Data","exit_code":"SUCCESS","extraProperties": {"entity":{"processingtime":{"unit":"millisecond","lastsampletime":1511693682663,"name":"ProcessingTime","count":2, "description":"Average request processing time","starttime":1511693222100}},"childResources":{}}}

The following script extracts the value of the "count" key, and provides additional metadata for prometheus.io metric (avgRequestProcessingTime.js):


function apply(input) {
    var metric = JSON.parse(input);
    var value = metric.extraProperties.entity.processingtime.count;
    var output = {
        suffix: "avg",
        units: "ms",
        component: "requestprocessingtime",
        application: "problematic",
        value: value
    };
    return JSON.stringify(output);
}

A payara with installed firehose (28 kB Thin WAR) ships as docker image from docklands.

The image can be started with: docker run -d -p 4848:4848 -p 8090:8090 --name payara-firehose airhacks/payara-firehose. The port 8090 is opened in addition to 8080 for monitoring purposes only.

The following PUT-request sets the monitoring targets and uploads the extractor script at the same time:

curl -i -XPUT -H"Content-type: text/plain" -H"uri: http://localhost:4848/monitoring/domain/server/http-service/server/request/processingtime.json" --upload-file avgRequestProcessingTime.js http://localhost:8090/firehose/resources/configurations/avgProcessingTime

Now: curl http://localhost:8090/firehose/resources/metrics should respond with something like:

problematic_requestprocessingtime_ms_avg 30

firehose acts as a gateway, so you only have to setup a single target at prometheus side:


(...)
scrape_configs:
  - job_name: 'firehose'
    scrape_interval: 5s
    metrics_path: '/firehose/resources/metrics'
    static_configs:
      - targets: ['payara-firehose:8090']

See you at Java EE Microservices and Java EE Troubleshooting, Performance and Monitoring

Is Munich's airport too far? Learn from home: javaeemicro.services


Real World Java EE Workshops [Airport Munich]>

Adam Bien - November 25, 2017 07:19 AM
Implementing Connect- and Read Timeouts with JAX-RS 2.1 Client and Java EE 8

Java EE 8 with JAX-RS 2.1 comes with configuration for read and connect timeouts (in Java EE 7 you had to use vendor-specific properties):


import java.util.concurrent.TimeUnit;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class JAXRSClientTimeoutTest {

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

    @Test
    public void connectTimeout() {
        expected.expect(ProcessingException.class);
        Client client = ClientBuilder.
                newBuilder().
                connectTimeout(1, TimeUnit.MILLISECONDS).
                build();
        //no one listens here
        client.target("http://127.0.0.1").
                request().
                get();
    }

    @Test
    public void readTimeout() {
        expected.expect(ProcessingException.class);
        Client client = ClientBuilder.
                newBuilder().
                readTimeout(1, TimeUnit.MILLISECONDS).
                build();
        //airhacks.com is too slow to answer in 1ms
        client.target("http://airhacks.com").
                request().
                get();
    }
}

See you at Java EE 8 on Java 9, at Munich Airport, Terminal 2
Real World Java EE Workshops [Airport Munich]>

Adam Bien - November 24, 2017 12:06 PM
Combining JavaScript ES 6 Templates with HTML 5

Combining JavaScript (ES 6) Template Strings with HTML:

See you at Single Page Applications (SPAs) -- the "no frameworks, no migrations" approach, at Munich Airport, Terminal 2 or webstandards.training (online).
Real World Java EE Workshops [Airport Munich]>

DukeScript - November 20, 2017 11:03 PM
Apache HTML/Java API version 1.5.1

The HTML/Java API has recently been donated to the Apache Foundation. The incubating HTML/Java project (that forms the basis of DukeScript portability) successfully passed Apache diligence verification and published version 1.5.1. To bring you the best features of the Apache released version, there is a new set of DukeScript Maven Archetypes available: uploaded to Maven central as version 0.18. In addition to that the archetypes also come with support for MobiDevelop version of RoboVM. Use via command line as:

$ mvn archetype:generate 
	-DarchetypeGroupId=com.dukescript.archetype
	-DarchetypeArtifactId=knockout4j-archetype  # or cru4j-archetype or visual-archetype
	-DarchetypeVersion=0.18 # or newer version
        -Diospath=client-ios # if you want iOS support
$ cd the_created_project
$ mvn install
$ mvn -f client exec:exec
$ mvn -f client-ios robovm:iphone-sim

or follow the visual tutorial to get started from an IDE.

APIDesign - Blogs - November 20, 2017 12:33 PM
Type-safe Parsing of JSON without any Reflection

In need of compiling Java ahead-of-time? See jsonparse example showing a Maven project that can turn your Java code into self-contained, small (less than 5M) and effective code suitable for your microservice or lamda as a service setups. Thanks to SubstrateVM!

--JaroslavTulach 12:33, 20 November 2017 (UTC)

Adam Bien - November 19, 2017 03:57 PM
JAX-RS Client, javax.net.ssl.SSLHandshakeException and Solution

The following exception:


javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target
    at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:284)
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:278)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
        

is thrown during the initialization of JAX-RS / HTTPs connection and caused by the lack of a certificate in Java's keystore. A certificate import fixes the problem, for System Tests, however, a certificate verification is not required (except in cases where certificate verification is tested) and can be omitted:


public class SSLClientIT {
    
        private Client client;
    
        private String host = "https://...;
        private WebTarget tut;
    
        @Before
        public void init() throws KeyManagementException, NoSuchAlgorithmException {
            TrustManager[] noopTrustManager = new TrustManager[]{
                new X509TrustManager() {
    
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
    
                    @Override
                    public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                    }
    
                    @Override
                    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
            };
            
            SSLContext sc = SSLContext.getInstance("ssl");
            sc.init(null, noopTrustManager, null);
            
            this.client = ClientBuilder.newBuilder().
                    sslContext(sc).
                    build();
            this.tut = this.client.target(this.host);
        }
    
        @Test
        public void get() {
            String result = this.tut.request().get(String.class);
            System.out.println("result = " + result);
        }
    
    }

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.
Real World Java EE Workshops [Airport Munich]>

Adam Bien - November 16, 2017 11:08 AM
Convenient http filtering with Servlet 4.0 and Java EE 8

HttpFilter was introduced with JSR 369 / Servlet 4.0 and Java EE 8.

The HttpServletRequest and HttpServletResponse parameters are directly passed to the HelloFilter#doFilter method:


import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebFilter("/*")
public class HelloFilter extends HttpFilter {

    @Override
    protected void doFilter(HttpServletRequest req, HttpServletResponse res, 
    FilterChain chain) throws IOException, ServletException {
        chain.doFilter(req, res);
        res.getWriter().print(" is great");
    }
}

The servlet does not know anything about the HelloFilter:


@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.getWriter().print("Java EE 8");
    }

}

curl (...)/HelloServlet returns Java EE 8 is great.

See you at Java EE 8 on Java 9, at Munich Airport, Terminal 2
Real World Java EE Workshops [Airport Munich]>