Č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 - 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]>

Adam Bien - November 15, 2017 08:39 AM
Fetching content reactively with JAX-RS 2.1 client and Java EE 8

Java EE 8 with JAX-RS 2.1 / JSR-370 introduced a JAX-RS Client API integrated with CompletionStage (aka reactive client).

Now an asynchronous request may return a Java 8 CompletionStage which allows a pipeline-style programming:


import java.util.concurrent.CompletionStage;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import org.junit.Before;
import org.junit.Test;


public class ReactiveClientTest {

    private WebTarget tut;

    @Before
    public void initClient() {
        this.tut = ClientBuilder.
        newClient().target("http://airhacks.com");
    }


    @Test
    public void reactive() throws InterruptedException {
        CompletionStage<Response> stage = this.tut.
                request().
                rx().
                get();
        stage.
                thenApply(req -> req.readEntity(String.class)).
                thenAccept(System.out::println);
        Thread.sleep(500);
    }

}

The JAX-RS 2.1 client requires the following dependencies:


<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>2.26</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>2.26</version>        
</dependency>

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

Adam Bien - November 13, 2017 02:15 PM
Code review, reports, NoSQL, BCE, Async and State -- or 44th airhacks.tv

WebStandards, microservices, reports, dealing with state in asynchronous JAX-RS, interactive code reviews, NoSQL,BCE, or 44th airhacks.tv is available:

Any questions left? Ask now: https://gist.github.com/AdamBien/53ea02999adaa8c328af43c01583aa68 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 - November 10, 2017 07:51 AM
Reuse, Tech Impact, Microservices, WebStandards -- a JavaONE 2017 interview

During JavaONE 2017 I was interviewed in the Developer Lounge about reuse, technology impact, microservices, my sessions and Java EE:

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 08, 2017 09:54 AM
Unskippable Maven Tests

The following maven plugin configuration introduces "unskippable" unit tests:

    
<build>
<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.20.1</version>
        <configuration>
            <skipTests>false</skipTests>
        </configuration>
    </plugin>
</plugins>
</build>


Even with the mvn clean install -DskipTests system property, all unit tests are still going to be executed.

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 07, 2017 09:32 AM
Using Chrome Developer Tools as an IDE / Editor

The Chrome's Developer Tools can be not only used to inspect the DOM, CSS and JavaScript, but also as an IDE / editor with write access to local project files:

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]>

Adam Bien - November 06, 2017 08:56 AM
HTML 5 Progressbars, Code Reviews, JAXB deprecation, Virtual DOM speed, Java SE Release and EE4j, EJB Timers in Cluster or 44th airhacks.tv

Topics for the 44th airhacks.tv (http://www.ustream.tv/channel/adambien) show 6th November, 2017 CET:

  1. JavaONE talk: Java EE heavyweight or lightweight Mythbusters and the comparison to Spring
  2. How to build a progressbar with HTML 5
  3. JAXB deprecation in Java9
  4. Virtual DOM, vs createElement, vs (...) performance
  5. Reference Implementations of EE4J
  6. Issue with org.eclipse.ee vs. javax.*
  7. Impact of Java SE release strategy to EE4j or JavaEE
  8. EJB Timer synchronization in cluster
  9. DB Views vs. JPA for reports?
  10. Architectural considerations with REST and Redis
  11. Critique of the "Roller blogger engine" Java EE clone
  12. Accessing SFSB from SLSB
  13. SFSB and scalability
  14. State and async JAX-RS

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

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


Real World Java EE Workshops [Airport Munich]>

Adam Bien - November 05, 2017 03:02 PM
A Conversation with Sebastian Daschner about CQRS, Java EE, EE4J, JavaONE

A conversation with Sebastian Daschner about Java EE, EE4J, JavaONE 2017, Microprofile, CQRS, JAX-RS analyzer and his: "Architecting Modern Java EE Applications book (amazon link)"

Subscribe to airhacks.fm podcast via: RSS iTunes or listen now.

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


Real World Java EE Workshops [Airport Munich]>

Adam Bien - November 01, 2017 05:14 AM
System.Logger--the minimalistic logging interface in Java 9

Java 9 comes with a minimal logging interface: System.Logger with default implementation returned by System#getLogger:


@Test
public void log() {
    System.Logger LOG = System.getLogger(LoggerTest.class.getName());
    System.out.println("Default System.Logger implementation: " + LOG.getClass().getName());
    LOG.log(System.Logger.Level.INFO, "hello java 9 logging");
}

output:

    Default System.Logger implementation: sun.util.logging.internal.LoggingProviderImpl$JULWrapper
    Nov 01, 2017 5:56:46 AM com.airhacks.logging.LoggerTest log
    INFO: hello java 9 logging

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

Adam Bien - October 31, 2017 10:14 AM
Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService

Java EE 8 with CDI 2.0 introduced asynchronous CDI Events. The Event interface was extended with the fireAsync method and an optional NotificationOptions parameter.

Now you can send events asynchronously, also using the injected ManagedExecutorService instance:


import java.time.LocalTime;
import java.util.concurrent.CompletionStage;
import javax.annotation.Resource;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.concurrent.ManagedExecutorService;
import javax.enterprise.event.Event;
import javax.enterprise.event.NotificationOptions;
import javax.inject.Inject;

@Startup
@Singleton
public class EventSource {

    @Inject
    Event<String> fireAlarm;
    
    @Resource
    ManagedExecutorService threadPool;

    @Schedule(second = "*/5", minute = "*", hour = "*")
    public void send() {
        String event = "fire " + System.currentTimeMillis();
        CompletionStage<String> completion = this.fireAlarm.
        fireAsync(event, NotificationOptions.ofExecutor(threadPool)); // returns immediately
        completion.thenAccept(this::eventDelivered);
    }

    void eventDelivered(String event) {
        //...receipt after delivery
    }
}
Asynchronous events are received with the @ObservesAsync annotation:


import java.time.LocalTime;
import javax.enterprise.event.ObservesAsync;

public class EventSink {

    public void onFireNotification(@ObservesAsync String event) {
       //...
    }

}

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


Real World Java EE Workshops [Airport Munich]>

Adam Bien - October 29, 2017 05:31 PM
Updating JsonObjects with JSON-P 1.1 and Java EE 8

Java EE 8 with JSON-P 1.1 ("JavaTM API for JSON Processing", JSR-374) introduced an overloaded Json#createObjectBuilder(JsonObject input) method which uses the JsonObject to set the initial state of the builder.

The pre-initialialization significantly simplifies updates:


import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
//...
            
@Test
public void jsonObjectUpdate() {
    String key = "update";
    String JAVA_EE_8 = "is easy with Java EE 8";

    JsonObject initial = Json.createObjectBuilder().
            add(key, "was hard in Java EE 7").
            build();

    JsonObject updated = Json.createObjectBuilder(initial).
            add(key, JAVA_EE_8).
            build();

    assertThat(updated.getString(key), is(JAVA_EE_8));
    assertThat(updated.size(), is(1));
}    

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