Tuesday, September 18, 2018

Micronaut for Java EE/Jakarta EE Developers

There is a new microservices framework in town called Micronaut.  In this post, I'll discuss how I've ventured into working with the Micronaut framework from a Java EE/Jakarta EE perspective.  I am a Java EE developer, so developing microservices using solutions such as Eclipse MicroProfile are closer to my line of expertise, but Micronaut caught my attention since it offers the following abilities:

- Develop in Java, Groovy, or Kotlin
- Easy to test..fully integrated testing with Spock or JUnit
- Embedded Server & Compile Time HTTP Client
- Easy packaging for Docker
- Fast startup time, low memory consumption
- Fully Reactive

As an enterprise developer at heart, my first thought usually goes to the database, as the majority of applications that I author utilize an RDBMS.  I found the number of examples using Micronaut with an RDBMS to be few and far between, so I thought it may be useful for me to create another example for that use case.  In this example, I utilize PostgreSQL.  However, most other RDBMS are also supported.  This article is not meant to be a full explanation of installing Micronaut or utilizing all of the many Micronaut features.  Instead, it is a primer for those looking to get started utilizing Micronaut with a relational database...particularly geared towards those with some Java EE/Jakarta EE background.

In my particular case, I am interested in quickly spinning up Microservices that are fully testable, extensible, and efficient.  Although I can do this with MicroProfile or standard Java EE, I thought it would be interesting to learn something new and also have the ability to utilize Groovy or Kotlin.  I also wanted to put a Java EE/Jakarta EE spin on it...so I'm using JPA for working with the data.  Many of the Micronaut examples utilize Groovy and GORM for persistence...but I likely wouldn't be using that in any of my applications.

The example was developed using Apache NetBeans 9.0 and the Command Line Interface (CLI) that comes packaged with Micronaut.  This particular example was written against Micronaut 1.0.0.M4.  In this case, I kept it simple and utilized only a single, basic database table for persistence within a PostgreSQL database.

To begin, I created an app by utilizing the CLI by issuing the following command:


mn create-app org.acme.books --features hibernate-jpa,jdbc-tomcat

This simply creates a skeleton for my app within a directory named "books", and the Application.java main class will be placed within the org.acme.books package.  By default, there are basic features supported by an application, but in this case I've added support for the Tomcat connection pool.  This will be utilized when creating database connections via the Java Persistence API (JPA).  The default application is also generated with support for the Gradle build system.  Therefore, a build.gradle is created, and that is the file in which dependency management will take place.  Note that an application can also be generated utilizing the Apache Maven build system, but I had issues running Maven projects under Micronaut 1.0.0.M4...so I stuck with Gradle for this example.

If using Apache NetBeans 9.0, you can install the "Groovy and Grails" and "Gradle" plugins (currently available in the NetBeans 8.2 plugin center) to provide support for opening the project.  Once this is completed, the project can be opened within NetBeans and development can begin.  After installing the plugins and opening the project within Apache NetBeans, the completed project structure should look like that in the following figure:



To provide support for the PostgreSQL database, I added the dependencies to build.gradle:

compile group: 'org.postgresql', name: 'postgresql', version: '42.2.5'

Next, I opened up the application.yml file and added a datasource for the application.  This is the file that takes place of a persistence.xml within a traditional Java EE application.  Also, JPA support is added via this file, indicating which package includes the entity classes, as well as configuration of Hibernate.  Port 8080 is also set, as by default Micronaut will choose a random port on which to start the server.  The full sources of application.xml are as follows:

micronaut:
    application:
        name: books
                
#Uncomment to set server port
    server:
        port: 8080

---
datasources:
    default:
        url: jdbc:postgresql://localhost/postgres
        username: postgres
        password: yourpassword
        driverClassName: org.postgresql.Driver
        connectionTimeout: 4000
jpa:
  default:
    packages-to-scan:
        - 'org.acme.domain'
    properties:
      hibernate:
        hbm2ddl:
          auto: update
          show_sql: true

Now that the configuration is out of the way, I can get to the fun part...development.  In this example, I create a basic service allowing one to create, read, update, or delete records in the BOOK table.  The automatically generated Application class within the org.acme package, which starts the service.

package org.acme;

import io.micronaut.runtime.Micronaut;

public class Application {

    public static void main(String[] args) {
        Micronaut.run(Application.class);
    }
}

To begin development, create two packages within the application for organizing the source code.  First, create org.acme.domain, which will contain the entity class.  Next, create org.acme.book, which will contain the implementation classes.  Create a Book.java class within the org.acme.domain package, which will be the entity class containing a standard JPA mapping for the database.  In this case, note that I utilize java.time.LocalDate for the date fields, and I utilize a database sequence generator for population of the primary key.  The sources are as follows:


package org.acme.domain;

import java.time.LocalDate;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

/**
 * JPA Mappings for the BOOK database table.
 */
@Entity
@Table(name="BOOK")
public class Book {
    
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE,
    generator="book_generator")
    @SequenceGenerator(name="book_generator",sequenceName="book_s", allocationSize=1)
    private Long id;
    
    @Column(name="PUBLISH_DATE")
    @NotNull
    private LocalDate publishDate;
    
    @Column(name="TITLE")
    @NotNull
    private String title;
    
    @Column(name="AUTHOR_FIRST")
    @NotNull
    private String authorFirst;
    
    @Column(name="AUTHOR_LAST")
    @NotNull
    private String authorLast;
    
    private Long pages;
    
    public Book(){}
    
    public Book(@NotNull Long id, @NotNull LocalDate publishDate, @NotNull String title, String authorFirst, String authorLast, Long pages){
        this.id = id;
        this.publishDate = publishDate;
        this.title = title;
        this.authorFirst = authorFirst;
        this.authorLast = authorLast;
        this.pages = pages;
    }

    public Book(@NotNull LocalDate publishDate, @NotNull String title, String authorFirst, String authorLast, Long pages){
        this.publishDate = publishDate;
        this.title = title;
        this.authorFirst = authorFirst;
        this.authorLast = authorLast;
        this.pages = pages;
    }

    /**
     * @return the id
     */
    public Long getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @return the publishDate
     */
    public LocalDate getPublishDate() {
        return publishDate;
    }

    /**
     * @param publishDate the publishDate to set
     */
    public void setPublishDate(LocalDate publishDate) {
        this.publishDate = publishDate;
    }

    /**
     * @return the title
     */
    public String getTitle() {
        return title;
    }

    /**
     * @param title the title to set
     */
    public void setTitle(String title) {
        this.title = title;
    }

    /**
     * @return the authorFirst
     */
    public String getAuthorFirst() {
        return authorFirst;
    }

    /**
     * @param authorFirst the authorFirst to set
     */
    public void setAuthorFirst(String authorFirst) {
        this.authorFirst = authorFirst;
    }

    /**
     * @return the authorLast
     */
    public String getAuthorLast() {
        return authorLast;
    }

    /**
     * @param authorLast the authorLast to set
     */
    public void setAuthorLast(String authorLast) {
        this.authorLast = authorLast;
    }

    /**
     * @return the pages
     */
    public Long getPages() {
        return pages;
    }

    /**
     * @param pages the pages to set
     */
    public void setPages(Long pages) {
        this.pages = pages;
    }
   
    @Override
    public String toString() {
        return "Book{" +
            "id=" + id +
            ", publishDate='" + publishDate + '\'' +
            ", title='" + title + '\'' +
            ", authorFirst='" + authorFirst + '\'' +
            ", authorLast='" + authorLast + '\'' +
            ", pages='" + pages +
            '}';
    }
}

In a Micronaut application, HTTP requests and responses need to be encapsulated in Serializable classes for processing, and therefore it makes sense to generate some simple "Plain Old Java Objects" (POJOs) for encapsulating the data that will be used within database operations.  In the same org.acme.domain package, I created two such classes, BookSaveOperation.java and BookUpdateOperation.java.  These classes will define the fields required for passing data from the HTTP request to the controller class.  The sources for BookSaveOperation.java are as follows (see the GitHub repository for full sources):


package org.acme.domain;

import java.time.LocalDate;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 *
 * @author Josh Juneau
 */
public class BookSaveOperation implements java.io.Serializable {
    
    
    @NotNull
    private LocalDate publishDate;
    
    @NotNull
    @NotBlank
    private String title;
    
    @NotNull
    @NotBlank
    private String authorFirst;
    
    @NotNull
    @NotBlank
    private String authorLast;
    
    private Long pages;
    
    public BookSaveOperation(){}
    
    public BookSaveOperation(LocalDate publishDate, String title,
                    String authorFirst, String authorLast, Long pages){
        this.publishDate = publishDate;
        this.title = title;
        this.authorFirst = authorFirst;
        this.authorLast = authorLast;
        this.pages = pages;
    }

   // ...
   // getters and setters
   // ...
}

The application business logic occurs within a class which is much like an EJB or DAO implementation, and the class must implement an interface that has defined each of the business logic methods.  In this case, I created an interface org.acme.book.BookRepository.java, and define a few standard operational methods:

package org.acme.book;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import org.acme.domain.Book;

/**
 *
 */
public interface BookRepository {
    Book save(LocalDate publishDate, String title, String authorFirst, String authorLast, Long pages);

    Optional<Book> findById(Long id);

    void deleteById(Long id);

    List<Book> findAll();

    int update(Long id, LocalDate publishDate, String title, String authorFirst, String authorLast, Long pages);
}

Next, implement that interface within a class entitled org.acme.book.BookRepositoryImpl.java, and annotate as a @Singleton.  Since this is the class which will implement business logic, inject a PersistenceContext, which provides the JPA EntityManager that will be used for performing database operations.  Simply implement each of the operations outlined within the BookRepository interface, marking each with @Transactional (io.micronaut.spring.tx.annotation.Transactional), implying read only for those methods that will not modify any data.  The sources for BookRepositoryImpl.java are as follows:


package org.acme.book;

import io.micronaut.configuration.hibernate.jpa.scope.CurrentSession;
import io.micronaut.spring.tx.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.acme.domain.Book;

/**
 * Business logic for the service.
 */
@Singleton
public class BookRepositoryImpl implements BookRepository {
    @PersistenceContext
    private EntityManager entityManager;

    public BookRepositoryImpl(@CurrentSession EntityManager entityManager) {
        this.entityManager = entityManager;
    }
    
    @Override
    @Transactional
    public Book save(LocalDate publishDate, String title, String authorFirst, String authorLast, Long pages) {
        Book book = new Book(publishDate, title, authorFirst, authorLast, pages);
        entityManager.persist(book);
        return book;
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<Book> findById(Long id) {
        return Optional.ofNullable(entityManager.find(Book.class, id));
    }

    @Transactional(readOnly = true)
    public List<Book> findAll() {
        return entityManager
                .createQuery("SELECT b FROM Book b", Book.class)
                .getResultList();
    }

    @Override
    @Transactional
    public int update(Long id, LocalDate publishDate, String title, String authorFirst, String authorLast, Long pages) {
        return entityManager.createQuery("UPDATE Book b SET publishDate = :publishDate, title = :title, " +
                "authorFirst = :authorFirst, authorLast = :authorLast, pages = :pages where id = :id")
                .setParameter("publishDate", publishDate)
                .setParameter("title", title)
                .setParameter("authorFirst", authorFirst)
                .setParameter("authorLast", authorLast)
                .setParameter("pages", pages)
                .setParameter("id", id)
                .executeUpdate();
    }

    @Override
    @Transactional
    public void deleteById(Long id) {
        findById(id).ifPresent(book -> entityManager.remove(book));
    }

}


In an effort to explain the Micronaut application infrastructure from a Java EE perspective, I'll compare the implementation with a simple JAX-RS application.  Micronaut utilizes io.micronaut.http.annotation.Controller classes to perform the request-response handling for a service.  This is much like a JAX-RS controller class, with a few slight differences.  This very much reminds me of the Eclipse Krazo project, or MVC 1.0 for Java EE.  For instance, instead of annotating methods with the JAX-RS annotations javax.ws.rs.GET, javax.ws.rs.POST, or javax.ws.rs.Path, Micronaut uses io.micronaut.http.annotation.Get and io.micronaut.http.annotation.Post, among others.  The URI path for each of the methods can be directly declared via the @Get, @Post, @Put, @Delete annotations.  Each controller class will implement the functionality for the service and handles the request-response life cycle.  The business logic for persistence (contained within the BookRepositoryImpl class) is injected into the controller class via the @Inject annotation or via constructor injection.  In the sources for this example, constructor injection is used.

package org.acme.book;

import org.acme.domain.Book;
import io.micronaut.http.HttpHeaders;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Delete;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.annotation.Put;
import io.micronaut.validation.Validated;

import javax.validation.Valid;
import java.net.URI;
import java.util.List;
import org.acme.domain.BookSaveOperation;
import org.acme.domain.BookUpdateOperation;

@Validated
@Controller("/books")
public class BookController {

    protected final BookRepository bookRepository;

    public BookController(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    @Get("/")
    public List<Book> list() {
        return bookRepository.findAll();
    }

    @Put("/")
    public HttpResponse update(@Body @Valid BookUpdateOperation operation) {

        bookRepository.update(operation.getId(), operation.getPublishDate(),
                operation.getTitle(), operation.getAuthorFirst(), operation.getAuthorLast(), operation.getPages());
        return HttpResponse.noContent().header(HttpHeaders.LOCATION, location(operation.getId()).getPath());

    }

    @Get("/{id}")
    Book show(Long id) {
        return bookRepository
                .findById(id)
                .orElse(null);
    }

    @Delete("/{id}")
    HttpResponse delete(Long id) {
        bookRepository.deleteById(id);
        return HttpResponse.noContent();
    }

    @Post("/")
    HttpResponse<Book> save(@Body @Valid BookSaveOperation operation) {

        Book book = bookRepository.save(operation.getPublishDate(), operation.getTitle(),
                operation.getAuthorFirst(), operation.getAuthorLast(), operation.getPages());
        return HttpResponse
                .created(book)
                .headers(headers -> headers.location(location(book)));
    }

    protected URI location(Book book) {
        return location(book.getId());
    }

    protected URI location(Long id) {
        return URI.create("/books/" + id);
    }

}

Testing the Application


Micronaut provides easy testing with Spock or JUnit and an embedded server...making it easy to create tests for each of the controllers.  In this case, I utilize JUnit to test the application.  I created a testing class within the test folder of the project named org.acme.BookControllerTest.

package org.acme;

import io.micronaut.context.ApplicationContext;
import io.micronaut.core.type.Argument;
import io.micronaut.http.HttpHeaders;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.client.HttpClient;
import io.micronaut.runtime.server.EmbeddedServer;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import org.acme.domain.Book;
import org.acme.domain.BookSaveOperation;
import org.acme.domain.BookUpdateOperation;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Test cases for BookController
 */
public class BookControllerTest {

    private static EmbeddedServer server;
    private static HttpClient client;
    private  Book book;

    HttpRequest request;
    HttpResponse response;
    Long id;
    List<Long> bookIds = new ArrayList<>();

    @BeforeClass
    public static void setupServer() {
        server = ApplicationContext.run(EmbeddedServer.class);
        client = server.getApplicationContext().createBean(HttpClient.class, server.getURL());
    }

    @AfterClass
    public static void stopServer() {
        if (server != null) {
            server.stop();
        }
        if (client != null) {
            client.stop();
        }
    }

    @Test
    public void testInsertBooks() {

        request = HttpRequest.POST("/books", new BookSaveOperation(LocalDate.now(), "Java EE 8 Recipes", "Josh", "Juneau", new Long(750)));
        response = client.toBlocking().exchange(request);

        assertEquals(HttpStatus.CREATED, response.getStatus());

        request = HttpRequest.POST("/books", new BookSaveOperation(LocalDate.now(), "Java 9 Recipes", "Josh", "Juneau", new Long(600)));
        response = client.toBlocking().exchange(request);
        id = entityId(response, "/books/");

        assertEquals(HttpStatus.CREATED, response.getStatus());

       
    }

    @Test
    public void testBookRetrieve() {
        request = HttpRequest.GET("/books");
        List<Book> books = client.toBlocking().retrieve(request, Argument.of(List.class, Book.class));
        // Populate a book instance for later
        for(Book b:books){
            book = b;
        }
        assertEquals(2, books.size());

        

    }
    
    @Test
    public void testBookOperations() {
        request = HttpRequest.GET("/books");
        List<Book> books = client.toBlocking().retrieve(request, Argument.of(List.class, Book.class));
        // Populate a book instance for later
        for(Book b:books){
            book = b;
        }
        
        request = HttpRequest.PUT("/books/", new BookUpdateOperation(book.getId(),
                book.getPublishDate(),
                "Java 10 Recipes",
                book.getAuthorFirst(),
                book.getAuthorLast(),
                book.getPages()));

        response = client.toBlocking().exchange(request);

        assertEquals(HttpStatus.NO_CONTENT, response.getStatus());

        request = HttpRequest.GET("/books/" + book.getId());
        book = client.toBlocking().retrieve(request, Book.class);
        assertEquals("Java 10 Recipes", book.getTitle());

        testDelete();

    }
    
    
    public void testDelete(){
       request = HttpRequest.GET("/books");
        List<Book> books = client.toBlocking().retrieve(request, Argument.of(List.class, Book.class));
        // Populate a book instance for later
        for(Book b:books){
            request = HttpRequest.DELETE("/books/" + b.getId());
            response = client.toBlocking().exchange(request);
            assertEquals(HttpStatus.NO_CONTENT, response.getStatus());
        }
    }

    Long entityId(HttpResponse response, String path) {
        String value = response.header(HttpHeaders.LOCATION);
        if (value == null) {
            return null;
        }
        int index = value.indexOf(path);
        if (index != -1) {
            return Long.valueOf(value.substring(index + path.length()));
        }
        return null;
    }
}

Walk-Through of the Logic in Testing Class


In the method that runs @BeforeClass, the HTTP server and client are created.  Similarly, when the tests have finished executing, the method that is annotated with @AfterClass is invoked, which stops the server if it is running.

From within the textInsertBooks() method, two new book records are created by passing new BookSaveOperation objects populated with data to the service that is available via the "/books" path with the @Post designation.  In this case, the controller method  BookController.save() is invoked.  Taking a look at the save() method, you can see that the method simply passes the contents of BookSaveOperation to the BookRepository.save() business method (utilizing the interface), persisting the object.  In the end, an HttpResponse is returned.

The testBookRetrieve() method calls upon the service that is available via the "/books" path containing the @Get designation.  This, in-turn, calls upon the BookController.list() method, which performs a findAll() on the BookRepository, returning a List of Book objects.

The testBookOperations() method is responsible for performing updates to the records.  First, the list of Book objects is retrieved from the BookController, and then one of the books is updated via the BookController.update() method by populating a BookUpdateOperation object with the contents to be updated.

** Keep in mind, the BookSaveOperation.java and BookUpdateOperation.java objects are simply POJOs that are used to move the data

Lastly, the testDelete() method is invoked, which traverses the List of Book objects, calling upon the BookController.delete() method via the service call to the "/books" path and invoking the method designated as @Delete.

To execute the tests, simply right-click the project in NetBeans and choose "Test", or use the command line to invoke using the following command

./gradlew test

If the database table has not yet been created, then it will be generated for you.  Note that you may need to modify the database configuration within application.yml accordingly for your environment.

Running the Service

Micronaut is self-contained, allowing a service to be executed using the embedded server which is built on Netty.  This can be done by right-clicking the project in Apache NetBeans and selecting "Run".  You could also go to the command line and invoke using the following command:

./gradlew run

You should see the URL on which the server is hosted displayed within the output in the terminal or Apache NetBeans output panel.

Summary


As a Java EE developer, I have to say that Micronaut does have a different development approach.  It is not too much different than that of Spring Boot or Grails, but it is different enough that it took me some time to find my way around.  In the end, I find it an easy to use framework that has a lot of potential for quickly developing services or scheduled tasks, while still harnessing some of the concepts from Java EE/Jakarta EE.  

There are a number of features that I've not played much with yet, such as creating scheduled tasks via the Micronaut framework, and developing using Groovy or Kotlin, rather than Java.  I hope to follow up to this post in the future with more information for Java EE and Jakarta EE developers who are interested in beginning their journey with Micronaut.

Friday, June 22, 2018

Apache NetBeans 9.0 - How to Build & Run the Latest

In my last post, I spoke about how to obtain the Release Candidate of Apache NetBeans 9.0.  There have been some changes made since the Release Candidate (including the addition of a very nice updated splash screen), so in this post I will cover how to build and run the latest sources.  I really is quite simple to run the latest code...here's how:

1)  Clone the latest source code from the GitHub repository to your local machine:

git clone https://github.com/apache/incubator-netbeans.git

2)  Open your terminal and traverse inside of the cloned directory named "incubator-netbeans"

3)  Build the IDE using Apache Ant.  If you do not have it installed, please download from here: https://ant.apache.org/

To build, simply issue the "ant" command from within the "incubator-netbeans" directory.



4)  The build process will take several minutes, as it obtains all of the dependencies and performs the compilation process.  Once completed, open the incubator-netbeans/nbbuild directory, and you should see a directory entitled "netbeans".  Inside this directory are all of the files required to run the Apache NetBeans IDE.  You can run the IDE by invoking the incubator-netbeans/nbbuild/netbeans/bin/netbeans executable.


Once the executable is started, you will be presented with the new Apache NetBeans 9.0 splash screen, and you can then begin to use the latest build.



Monday, May 21, 2018

Apache NetBeans 9.0 - Release Candidate Review



First, I want to thank all of the developers that have been working hard on the Apache NetBeans 9.0 release.  I am on the mailing lists and these developers have been working around the clock to ensure that this release is solid.  I was part of the NetBeans 9.0 NETCAT testing team for the profiler tool this year.  I only contributed a few hours of testing, but it was a great experience to be part of the team helping to move NetBeans forward.  There are plenty of people who have contributed dozens of hours...so thank you!

Release Candidate 1 (currently in testing and not yet officially released) can be downloaded using the following links:

Build Artifacts:
https://dist.apache.org/repos/dist/dev/incubator/netbeans/incubating-netbeans-java/incubating-9.0-rc1-rc1

ZIP Artifact:
https://dist.apache.org/repos/dist/dev/incubator/netbeans/incubating-netbeans-java/incubating-9.0-rc1-rc1/incubating-netbeans-java-9.0-rc1-source.zip

This release of NetBeans constitutes all of the modules within the Apache NetBeans GitHub repository ((https://github.com/apache/incubator-netbeans).  These modules include the NetBeans Platform and the full IDE for Java SE development.

There are still a number of tasks that will need to be performed before moving forward, but Release Candidate 1 is a huge step.  In the coming days/weeks, there will likely be another release candidate which will include some final pieces, such as a new splash screen.  We are getting very close to the official Apache NetBeans IDE 9.0 release.

Keep in mind that this first release does not include the transfer of all NetBeans modules.  For instance, the Java EE modules have not yet been transferred or included in Apache NetBeans 9.0.  That transfer will occur sometime in the future.  However, it is still possible to develop Java EE applications using Apache NetBeans 9.0 by simply installing the Java EE related NetBeans 8.2 plugins.  I am doing this today and it works well!

Stay tuned during the coming weeks for the official release of Apache NetBeans 9.0.  In the meantime, get involved!  Please download the Release Candidate and take it for a spin.  Join the NetBeans developer mailing list to provide feedback and/or vote on upcoming release candidates.

https://netbeans.apache.org/


Wednesday, November 29, 2017

Easy Java EE Microservices with Payara Micro

Wondering how to get started with Java EE Microservices?  It only takes a few quick steps to deploy a Microservice using Java EE APIs.  Many think that Java EE is too heavyweight for use with Microservices, but that is simply not the case...especially if you only utilize the Java EE specifications that are required by your service.  In this brief post, I'll demonstrate how to quickly develop a Microservice with Java EE and then deploy to Payara Micro.

To download the example project, please go to GitHub: https://github.com/juneau001/SimpleService

For the purposes of this example, I will utilize NetBeans, but any Java IDE will suffice.  To get started, create a Maven web application and name it SimpleService.  Next, create two Java packages:  org.simpleservice and org.simpleservice.entity.  Once complete, the project should resemble the following figure:



Now many believe that a Microservice should not connect to an enterprise database, but I will leave that for those who wish to debate.  In this example, I will connect this service to a central Apache derby database to obtain data because I believe this to be a very likely scenario in many organizations.  In this case, we'll create a "Suggested Name" database web service, which will query a database table of suggested names for the upcoming EE4J platform.  To create the infrastructure, connect to a local Apache Derby database and create it using the following SQL:

create table SUGGESTED_NAME (
id numeric primary key,
name varchar(150));

insert into suggested_name values(1, 'Open EE');
insert into suggested_name values(2, 'Open JOE');
insert into suggested_name values(3, 'Cappucino');

Next, open the Maven POM file for the SimpleService project and add the following dependencies:

<dependencies>
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.0.Final</version>
        </dependency>
        <dependency>
            <groupId>javax.ejb</groupId>
            <artifactId>javax.ejb-api</artifactId>
            <version>3.2</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>eclipselink</artifactId>
            <version>2.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
            <version>2.5.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derbyclient</artifactId>
            <version>10.14.1.0</version>
        </dependency>
    </dependencies>

Note that there is no Java EE dependency.  This is because I am utilizing only those dependencies that are required for the service.  Each dependency is added separately.

Next, create a package org.simpleservice.entity, and create an entity class named SuggestedName within it.  For brevity, I'm not going into all of the sources here, but you can check the sources out on GitHub (https://github.com/juneau001/SimpleService).

We'll need to implement our JAX-RS web service class next.  To configure the Java EE application for JAX-RS, let's create a class named ApplicationConfig and place it within the org.simpleservice package:
import java.util.Set;
import javax.ws.rs.core.Application;

/**
 *
 * @author Juneau
 */
@javax.ws.rs.ApplicationPath("rest")
public class ApplicationConfig extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new java.util.HashSet<>();
        resources.add(org.simpleservice.SuggestedNameService.class);
        return resources;
    }
}

Next, I'll create the JAX-RS web service class itself, and I will name it SuggestedNameService.  Here are the sources for the SuggestedNameService class.  Note that I have injected a Persistence Unit.  I will get to that next.


@Stateless
@Path("suggestedNameService")
public class SuggestedNameService {
    @PersistenceContext(unitName = "SimpleService_1.0PU")
    private EntityManager em;
    @GET
    @Path("{id}")
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public SuggestedName find(@PathParam("id") BigDecimal id) {
        SuggestedName suggestedName = null;
        try {
            suggestedName = (SuggestedName) 
                    em.createQuery("select object(o) from SuggesetedName o " +
                    "where o.id = :id")
                    .setParameter("id", id)
                    .getSingleResult();
        } catch (NoResultException ex){
            System.out.println("Error: "  + ex);
        }
        return suggestedName;
    }
   
    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public List<SuggestedName> findAll() {
        List<SuggestedName> suggestedNames = null;
        try {
            suggestedNames = em.createQuery("select object(o) from SuggestedName o")
                    .getResultList();
        } catch (NoResultException ex){
            System.out.println("Error: "  + ex);
        }
        return suggestedNames;
    }
    protected EntityManager getEntityManager() {
        return em;
    }
    
}

Since this service will connect to a database, I will create a persistence unit for the project.  This can be easily done in NetBeans by right-clicking the project and choosing New->Persistence->Persistence Unit.  Name the persistence unit SimpleService_1.0PU and use EclipseLink as the provider.  Do not add a data source at this point.

Once created, open the Persistence Unit and add the connection information.  In this case, I will connect to a JTA data source that I'll define next.  The data source is named DerbyDataSource, so the content of the Persistence Unit (persistence.xml) should look as follows:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="AuthorService_1.0PU" transaction-type="JTA">
    <jta-data-source>java:global/DerbyDataSource</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties/>
  </persistence-unit>
</persistence>

Create a web.xml deployment descriptor for the project.  If doing this within NetBeans, simply right-click the project and choose New->Web->"Standard Deployment Descriptor (web.xml) and click Finish.  Once the web.xml deployment descriptor has been generated, add the data source to it.

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
<data-source>
        <name>java:global/DerbyDataSource</name>
        <class-name>org.apache.derby.jdbc.ClientDriver</class-name>
        <server-name>localhost</server-name>
        <port-number>1527</port-number>
        <url>jdbc:derby://localhost:1527/acme</url>
        <user>acmeuser</user>
        <password>yourpassword</password> 
    </data-source>
</web-app>
That's it for the Java EE application.  You should now be able to compile the project into a WAR file and deploy to GlassFish, Payara, or another Java EE application server of your choice.  In this case, let's deploy to Payara Micro. 

To begin, download the latest Payara Micro JAR file from the website: https://www.payara.fish/payara_micro

Once downloaded, the server can be started up by opening a command prompt and executing the JAR with your local Java runtime by typing:

java -jar payara-micro-4.1.2.174.jar

To deploy the application (microservice) that we've created, simply utilize the --deploy option when executing the Payara Micro JAR, and point it to the SimpleService WAR file:

java -jar payara-micro-4.1.2.174.jar --deploy SimpleService-1.0.war

The SimpleService microservice can now be accessed via the following URL:  http://localhost:8080/SimpleService-1.0/rest/suggestedNameService





Saturday, November 04, 2017

Utilizing Apache NetBeans with JDK 9

Did you know that you can build Apache NetBeans from scratch today and utilize the latest JDK 9 features?  Here is how to do it:

Clone the NetBeans Incubator sources to your machine:

git clone https://github.com/apache/incubator-netbeans

Build using JDK 8 and Ant 1.9.9 by traversing into the cloned incubator-netbeans directory and invoking the ant build:

ant

Once the build is complete, traverse into the nbbuild/netbeans directory to see the resulting IDE build.  Run the IDE by invoking the executable or shell script contained within nbbuild/netbeans/bin.





Friday, September 08, 2017

Open EE: My Thoughts on an Open Java EE Platform

About two years ago, thousands of Java developers attended the JavaOne 2015 conference and learned about specifications and features that would be part of the Java EE 8 platform.  These features included the MVC 1.0 specification, Java EE Security 1.0, Microservices, CDI and more.  Java EE 8 was shaping up to be a great follow-up to the excellent Java EE 7 release.

After JavaOne 2015, progress and news around Java EE went silent.  In early January 2016, I received an invite to a Slack group that was created by some members of the Java EE community.  On the Slack channel, there were discussions around the halt of Java EE, and what the community may be able to do in order to keep it moving forward.  I was humbled by the sense of community from the members of the channel and the devotion to the platform was very evident.  Not long after, the Java EE Guardians were formed, focusing on publicizing the stall of Java EE.  The group put forth effort pressuring Oracle to make a statement and continue moving Java EE forward.  Especially in this fast paced space, looming silence regarding the future of any technology can be taxing on those involved.  Others worked on the Java EE specifications as much as possible, making strides forward.

After almost a year of silence, we started to hear music around Java EE again, and at JavaOne 2016 Oracle unveiled the plan to continue moving Java EE 8 forward, albeit a bit differently than originally planned.  The newly envisioned Java EE centered around Microservices and dropped a few of the specifications that no longer fit into the puzzle.  MVC 1.0, JMS 2.1, and Management 2.0 were taken out of the picture, while the newly proposed Health Checking and Configuration APIs were added.  MVC was eventually handed over to the community, which I think was a great move.  The Health Checking and Configuration APIs, which were clearly aimed toward microservices support, were later taken out of the picture for Java EE 8 due to lack of time.  Java EE 8 had more community involvement than any previous Java EE release, and much of this is likely due to the hiatus.  Java EE 8 moves forward, albeit a bit more lean than originally planned, we are moving forward.

Now, nearing the JavaOne 2017 conference, we are on the heels of a Java EE 8 release.  This release includes much of the original core Java EE 8 plan, bringing the Java EE platform in-line with Java SE 8.  It also enhances CDI support throughout the specifications, brings forth Security 1.0, which is long overdue, and JSON-B, closing the JSON to Java conversion gap that was left after JSON-P was released.  Java EE 8 will be a solid release, and I am thankful to all who are involved in making it happen.  I am sorry to say that I will not be at the JavaOne conference this year when it will likely be released, but I know that my colleagues will keep me in-tune with the latest news coming from the conference!  If you are going, make sure you check out the many great Java EE talks that will be presented.

Almost like a professional sports superstar going out on a high note, Oracle recently announced that they are planning to open source Java EE.  I have to applaud Oracle for all of the great work they've done and the support that they've given to Java EE through the years.  I am hopeful that they will remain engaged even after Java EE is open sourced, as they are a very important player in this space.  In my mind, they chose a perfect time to announce the opening of Java EE, as the Java EE 8 release will mark a great milestone making Java EE even more productive and relevant as one of the top application development platforms in the industry.  The community around Java EE seems as though it has never been more engaged than it is now.  Over the years since the cumbersome J2EE morphed into the productive platform that we call Java EE today, the community has continued to grow by the thousands.  The Java EE Guardians have thousands of supporters, each of them hoping to help move Java EE forward for years to come.

I see a great future for an open Java EE.  However, many questions are left to be answered.  Will the JCP still be used to manage the changes that are proposed for the platform?  Perhaps this is one of the questions that has the potential to impact the platform the most.  If the JCP will still be used to manage the platform, can it be changed in such a way that it will be conducive to a faster moving platform?  Do we want Java EE to become a faster moving platform, much to the likes of other frameworks such as Spring?

One of the main strongholds of Java EE is standardization.  If the open Java EE were to become more dynamic, can it maintain its place as a standard in the industry?  I think so.  I think that ideally the JCP could still be used to move the specifications forward, with a bit of a modernizing on the approach.  I like the idea of having shorter Java EE release cycles with fewer changes in each release.  Such an approach can really help the platform to retain its relevancy in this fast moving space.

What are your thoughts on the opening of Java EE?  I welcome it and look forward to seeing what is to come for JavaOne 2018.

Wednesday, July 26, 2017

Java EE 8: Start Testing Today

Java EE 8 will be finalized and ready for public use soon.  There is no better time to get started testing the new features than now.  You can do so by grabbing a copy of my Java EE 8 Playground project and deploying to GlassFish 5.

I've just updated the project to repair bugs and include better formatted table data within the tables.  I've also added a couple of examples:

- JSON-B example: Allows one to fetch the JSON for customer objects.

- CDI 2.0 Async:  Add a new Job object to see async event output in server log

GitHub Project:  https://github.com/juneau001/JavaEE8-Playground

Saturday, June 10, 2017

Java 9 Recipes Published!

A bit ahead of schedule, my latest book entitled Java 9 Recipes: A Problem-Solution Approach, has just been published!


This book is the 3rd Edition in the Java Recipes series.  It covers all of the information that was in the previous editions, including the new content for Java 9.  Specifically, you will learn how to use new Java 9 features including:


  • Modularity
  • Private Method Implementations in Interfaces
  • Process API Enhancements
  • New Streams API Enhancements
  • HTTP/2 Client API

I'd like to thank Apress for providing me with the opportunity to help share my knowledge of the Java platform.

For more information on using Java 9, check out the tutorials found in this post: https://www.javacodegeeks.com/java-9-tutorials

Wednesday, March 29, 2017

Testing the Java EE 8 Specifications

The Java EE 8 Platform has definitely been moving along within the past couple of months.  Specifications have been releasing early draft reviews, milestones, and even final releases.  As a matter of fact, JSR-372 has just gone final, as JSF 2.3 has been released.  For more information, please see Arjan's Post.  It had the privilege to be a part of the JSR-372 expert group, and I really appreciate the opportunity to work with these experts on a specification that I use every day.

I created a Github Project entitled the Java EE 8 Playground, and it includes a Java EE application that contains a number of the latest updates to those specifications that will be part of the Java EE 8 release.  I will make an effort to update this project often so that it includes current dependencies for the specifications.  I will also try to add demos for the specifications so that it will be easy to build upon the examples.  In the current project, some of the JSF 2.3 features are used.

It is important that as a community we test and provide feedback for the Java EE 8 specifications as they are being developed.  It is in these stages that you have a voice that can make a change to an upcoming specification.  Please test, read the latest specification documents, and provide feedback to the respective JSRs.

Java EE 8 Playground Project:  https://github.com/juneau001/JavaEE8-Playground

Java EE 8 JSRs:

JSR 365 (CDI 2.0):  https://www.jcp.org/en/jsr/detail?id=365
JSR 366 (Java EE 8):  https://www.jcp.org/en/jsr/detail?id=366
JSR 367 (JSON Binding):  https://www.jcp.org/en/jsr/detail?id=367
JSR 369 (Servlet 4.0):  https://www.jcp.org/en/jsr/detail?id=369
JSR 370 (JAX-RS 2.1):  https://www.jcp.org/en/jsr/detail?id=370
JSR 372 (JSF 2.3 - FINAL):  https://www.jcp.org/en/jsr/detail?id=372
JSR 374 (JSON  Processing 1.1):  https://www.jcp.org/en/jsr/detail?id=374
JSR 375 (Java EE Security 1.0):  https://www.jcp.org/en/jsr/detail?id=375
JSR 380 (Bean Validation 2.0):  https://www.jcp.org/en/jsr/detail?id=380

JSR 371 (MVC - No longer officially part of Java EE 8):  https://www.jcp.org/en/jsr/detail?id=371




Saturday, March 04, 2017

JSR 365 Update: Digging Into CDI 2.0

Contexts and Dependency Injection 2.0 (JSR 365), is an update to CDI 1.2, which is currently part of the Java EE 7 platform.  It is currently in Public Review stage.  For those of you who are not very familiar with CDI, it defines a powerful set of complimentary services that act as a gel that help to improve the coordination and structure of application code.  For more details, please visit the specification page.

CDI 2.0 expands the usability of the Contexts and Dependency Injection services to Java SE as well, as it will now target both the Java SE and Java EE platforms.  The CDI specification has been organized into 3 parts, Part I - Core CDI, Part II - CDI in Java SE, and Part III - CDI in Java EE.  The major changes for CDI 2.0 are as follows:

  • Better alignment with Java SE 8
  • API for booting CDI within a Java SE application
  • Ability to provide observer ordering
  • Ability to fire asynchronous events
  • New Configurators Interfaces for Service Provider Interface (SPI) elements
  • Ability to configure or veto an observer method in ProcessObserverEvent event
  • Support for inline instantiation of specific annotation types
  • Addition of the InterceptionFactory interface,  which allows to create a wrapper instance whose method invocations are intercepted by method interceptors and forwarded to a provided instance.
I encourage you to take a look at the CDI 2.0 Public Review Draft for more details on the specifics of each enhancement listed, as well as a complete listing of new features.  Read through the draft and provide feedback to the expert group.  All of the pertinent details for providing feedback can be found on the JSR 365 page.  To get started testing, create a new maven based Java EE application in your favorite IDE, and add the following dependencies:

<dependency>
    <groupid>javax.enterprise</groupid>
    <artifactid>cdi-api</artifactid>
    <version>2.0-PFD</version>
</dependency>
<dependency>
    <groupid>org.jboss.weld</groupid>
    <artifactid>weld-core-bom</artifactid>
    <version>3.0.0.Alpha14</version>
    <type>pom</type>
</dependency>

In this post, we will dig into one of the new features to get you started working with the API.  Let's take a look at asynchronous events.  Until CDI 2.0,  events could only be fired in a synchronous manner.  They've been enhanced in this latest iteration for asynchronous processing.  Here's how it works:

Create an event of some type.  Next, fire the event in an asynchronous manner, and handle accordingly once the event is complete.  In this example, I have created a MovieEvent class, which will be utilized whenever a persist event occurs for a Movie object.  The MovieEvent class is as follows:

public class MovieEvent {
    
    private String message;
    private Movie movie;
    
    public MovieEvent(String message, Movie movie){
        this.message = message;
        this.movie = movie;
    }
    
    public String getMessage(){
        return this.message;
    }
    
    public void setMessage(String message){
        this.message = message;
    }
    
    public Movie getMovie(){
        return this.movie;
    }
    
    public void setMovie(Movie movie){
        this.movie = movie;
    }
    
}

In the following scenario, we are firing an event when a new Movie is persisted.  The following code resides within a MovieController CDI bean of an example JSF application:

@Named("movieController")
@SessionScoped
public class MovieController implements Serializable {

    @EJB
    private com.mycompany.cditest.session.MovieFacade ejbFacade;
    private List items = null;
    private Movie selected;
    
    @Inject
    Event<MovieEvent> movieEvents;
. . .
   private void persist(PersistAction persistAction, String successMessage) {
        if (selected != null) {
            setEmbeddableKeys();
            try {
                if (persistAction != PersistAction.DELETE) {
                    getFacade().edit(selected);
                    movieEvents.fireAsync(new MovieEvent("New Movie Released", selected))
                            .whenComplete((event, throwable) -> {
                                if(throwable != null){
                                    System.out.println("Error has occurred: " + throwable.getMessage());
                                } else {
                                    System.out.println("Successful Movie Processing...");
                                }
                            });
                } else {
                    getFacade().remove(selected);
                }
                JsfUtil.addSuccessMessage(successMessage);
            } catch (Exception ex) {
                Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
                JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
            }
        }
. . .

When the event is fired, it creates a new MovieEvent object, and if it successfully completes then a message is printed to indicate success.  In this example, a stream is used to process the "whenComplete" action.

Feel free to clone the repository located at https://github.com/juneau001/CdiTest and take CDI 2.0 test for a spin.  This example is just one simple test of CDI 2.0.  You can clone and utilize this test project as a starting point to work with other aspects of the specification.  Keep an eye on JSR 365, which is currently in the Public Review Ballot stages.


Wednesday, September 28, 2016

JavaOne 2016 Follow-Up

I had the pleasure of attending JavaOne this year, and I can sum up the experience in one word:  Brilliant.  This year was much different than in years past for me, as I had one talk to co-present on Sunday and I had the rest of the week wide open for attending sessions.  As such, I've learned that it really is nice to have a lighter schedule at JavaOne so that you can take in all of the expertise and networking...that is what JavaOne is all about...learning from the experts and growing your network.  I also had my lovely wife along with for part of this trip, which made my stay in San Francisco very nice, as I finally took a few minutes to enjoy the city this year...never had done that in the past.

My conference experience started off with the excellent NetBeans party on Saturday evening.  I am a member of the NetBeans Dream Team, so many of my colleagues were in attendance at this party.  It was the first time I had seen many old friends, and it was great to have a chance to catch up without needing to worry about rushing to the next session.  I want to thank Geertjan Wielenga and Oracle for hosting this excellent event, and I cannot wait until the next Apache NetBeans party.

On Sunday at NetBeans Day, I had the pleasure of presenting "Enterprise Modeling of MVC and Java EE Artifacts" with experts Ivar Grimstad and Gaurav Gupta.  Ivar is on the expert group for JSR 371 (MVC 1.0)...which we hope to move forward for use with Java EE 8.  Gaurav is the lead developer for the excellent JPA Modeler tool.  During our session, Ivar gave an overview of MVC 1.0, Gaurav highlighted the JPA Modeler utility, and I demonstrated how the JPA Modeler could be utilized with JSF applications, as well as MVC 1.0.  I want to thank Geertjan again for getting the three of us together for this excellent talk.

The opening keynote was amazing.  A large portion was devoted to showing how the world is using Java, including the outstanding Mars rover presentation by Dr. Anita Sengupta (@Doctor_Astro).  It was amazing to see the complexity and detail that went into ensuring the Curiosity rover landed without issues.  Of course, Java 9 was mentioned, along with a demo of modularity and the jshell by Mark Reinhold...very informative, as always.

During the opening keynote, I anxiously awaited word on the status of Java EE, and after quite a long wait, the announcement was made.  I am very excited that Java EE 8 efforts are moving forward, albeit a bit differently than previously planned.  Essentially most of the specifications for Java EE 8 is moving forward, and it is proposed that the following be removed so that resources can spend time in other areas: JSR 371 (MVC 1.0) and JSR 368 (JMS 2.1), JSR 373 (Management 2.0).  I will cover my thoughts on these proposed dropped specifications in a follow-up post.  The main focus for Java EE 8 will be to start paving the path for a more micoservices focused platform, whereby Java EE 9 will be released a year later and it will include the full microservices implementation.  The addition of Health Checking and Configuration specifications would be beneficial for providing a standard means by which to monitor services and dynamically configure our applications.  Overall, it is great to see things moving forward for Java EE, although I do have some reservations on the overall approach.  I do not believe that every industry will adopt the microservices architecture, so there needs to be a path for those who will be continuing with the standard Java EE application architecture.

Rather than going through detail on each of the sessions that I had attended, I will provide a summary of my thoughts on the conference overall.  As I have said many times before, time is not our friend...and this certainly was the case this year at JavaOne, as there were too many great tutorials, sessions, and networking events that it was difficult to see everything.  Hats off to Sharat Chander and others at Oracle for organizing such a great conference.  I also want to thank the content review committees for reviewing and choosing such great conference tutorials and sessions...the content was excellent!

The tutorials and hands-on labs dealing with Microservices were hot this year.  I attended two of them myself.  One of them was a hands on lab that enabled us to develop Microservices using JBoss Forge and WildFly Swarm.  It was a fast pace tutorial covering everything from setting up Eclipse (unfortunately not my favorite IDE), through utilizing Forge, constructing services, and deployment.  I am glad I attended, as it gave me a different perspective on development from what I am used to.  The second was a tutorial on utilizing Payara Micro and the Payara MicroProfile.  I found this tutorial very in-depth, covering these technologies from the ground-up, with lots of detailed explanation.  I learned it is quite easy to add the Payara Microprofile to a project, simply by including the dependency in the POM:

<dependency>
   <groupId>fish.payara.extras</groupId>
   <artifactId>payara-microprofile</artifactId>
   <version>1.0</version>
   <scope>provided</scope>
</dependency>

Deploying is as simple as:

java -jar payara-microprofile-1.0.jar --deploy test-app.war 

I attended many key Java EE sessions, including those given by Linda DeMichiel and others leading the specifications.  All of these were informative, covering content from previous Java EE incarnations through what to expect in Java EE 8.  Linda's presentation on Monday went into a bit more detail on the plans for Java EE 8, and it is clear to see that Oracle is "all in" on moving forward with the newly proposed plan for Java EE 8...which is great!  Each of the specification-specific talks that I attended were excellent, including CDI 2.0,  JAX-RS 2.1, and JSF 2.3.  Great to hear from the experts for these areas.  I also took in a couple of other key talks:  Java EE Extendable to Functional by David Blevins, and 50 Java EE Best Practices by Ryan Cuprak and Michael Remijan...both great!

There were a lot of sessions on Java 9 and modularity this year.  I attended a session on modularity, which was a great introduction for those hadn't yet had a chance to experiment with it.  Docker was another hot topic at the conference, and I had the opportunity to attend a couple of sessions covering this great tech.

I had the privilege to attend the JCP Party on Monday evening.  Always an excellent opportunity to network with others in the JCP, and this year's event did not let us down.  The Chicago Java Users Group (CJUG), Bob Paulin, and myself won an award at the JCP Party on Monday evening for Adopt-a-JSR participants of the year.  This was a very nice surprise!  I also attended PartyOne, hosted by Tomitribe, ZeroTurnaround, BainCapital, and Hazelcast.  This was a great opportunity to network with so many experts...and there was also a great view of the Bay Bridge off the balcony.  I want to thank Tomitribe for the invitation!  Lastly, I attended the Oracle Appreciation Event, which was very nice.  The Oracle OpenWorld and JavaOne attendees had AT&T Park to themselves, and we got to see Sting and Gwen Stefani.  Great networking opportunity with many great friends.

Overall, JavaOne 2016 was another great conference...very glad to have been a part of it.  If you have not done so already, please take the Java EE Survey and provide your thoughts on the upcoming Java EE 8 proposal:

http://glassfish.org/survey

Thursday, September 15, 2016

NetBeans Java EE 8 MVC Plugin Enhancements

A while back, Geertjan Wielenga had posted about a NetBeans plugin that had been developed for the upcoming Java EE 8 MVC framework.  The plugin was originally developed by Manfred Riem, co-spec lead for JSR 371, and Geertjan had extended it to add functionality for viewing all of the MVC controllers within an application.  This plugin is a great start to a useful MVC plugin for NetBeans.

I've since taken the plugin and extended it further, adding the following enhancements:

  • NetBeans workspace now scanned to apply plugin only to those projects that contain MVC controller classes.
  • Ability to create a new MVC application which includes a basic controller class and corresponding view.
  • Ability to add new MVC controller class to a project.

Come and check out the new plugin functionality at JavaOne.  I have the honor of presenting along with Ivar Grimstad (JSR 371 Expert Group) and Gaurav Gupta (JPA Modeler) in the presentation UGF6435 -- Enterprise Modeling of MVC and Java EE Artifacts for NetBeans Day 2016.  I'll demo the plugin during the session, alongside the powerful JPA Modeler utility.  

Hope to see you there!

For more information on NetBeans IDE, please check out the Java NetBeans IDE Tutorial.

Friday, July 15, 2016

NetBeans 8.2 Profiler: Colored Results

One of the new features in NetBeans 8.2 is the ability to color profiler results differently based upon filters.  This can make things visually stand out, and easier to follow in the profiler output.

To enable colored profiler results, go into the NetBeans "Preferences"->"Java"->"Profiler" menu, as seen in Figure 1.  Check the box to "Use defined filters for coloring results".

Figure 1:  NetBeans Profiler Colored Filter Results

Add any filter(s) you wish, and assign a color to the results of those filters (Figure 2).  If you wish to display the output from one of the existing filters in a different color, click the tool icon and change the colors.  As you can see in the previous figure, I updated the Java EE Frameworks filter to be a green color.

Figure 2:  Assign Colors to Filters

After applying the colors to the filters, run the profiler and see the results!

Figure 3:  Colored Results!