Skip to main content

"Are Java EE / Jakarta EE Servers Dead?"--Tech Talk and Q&A

by admin at January 21, 2020 05:36 AM

"Are Jakarta EE Servers Dead?" - a Jakarta Tech Talk (with a bit Code Talk) about the role of application servers in the container / cloud age. Interactive Q&A included:


by admin at January 21, 2020 05:36 AM

Productivity with Plain Vanilla Web Components--airhacks.fm podcast

by admin at January 19, 2020 03:43 PM

Subscribe to airhacks.fm podcast via: spotify| iTunes| RSS

The #71 airhacks.fm episode with Robert Brem (@bremrobert) about:
"replacing dependencies and frameworks with web standards and Web Components to increase productivity"
is available for download.

by admin at January 19, 2020 03:43 PM

Jakarta EE 8 CRUD API Tutorial using Java 11

by rieckpil at January 19, 2020 03:07 PM

As part of the Jakarta EE Quickstart Tutorials on YouTube, I’ve now created a five-part series to create a Jakarta EE CRUD API. Within the videos, I’m demonstrating how to start using Jakarta EE for your next application. Given the Liberty Maven Plugin and MicroShed Testing, the endpoints are developed using the TDD (Test Driven Development) technique.

The following technologies are used within this short series: Java 11, Jakarta EE 8, Open Liberty, Derby, Flyway, MicroShed Testing & JUnit 5

Part I: Introduction to the application setup

This part covers the following topics:

  • Introduction to the Maven project skeleton
  • Flyway setup for Open Liberty
  • Derby JDBC connection configuration
  • Basic MicroShed Testing setup for TDD

Part II: Developing the endpoint to create entities

This part covers the following topics:

  • First JAX-RS endpoint to create Person entities
  • TDD approach using MicroShed Testing and the Liberty Maven Plugin
  • Store the entities using the EntityManager

Part III: Developing the endpoints to read entities

This part covers the following topics:

  • Develop two JAX-RS endpoints to read entities
  • Read all entities and by its id
  • Handle non-present entities with a different HTTP status code

Part IV: Developing the endpoint to update entities

This part covers the following topics:

  • Develop the JAX-RS endpoint to update entities
  • Update existing entities using HTTP PUT
  • Validate the client payload using Bean Validation

Part V: Developing the endpoint to delete entities

This part covers the following topics:

  • Develop the JAX-RS endpoint to delete entities
  • Enhance the test setup for deterministic and repeatable integration tests
  • Remove the deleted entity from the database

The source code for the Maven CRUD API application is available on GitHub.

For more quickstart tutorials on Jakarta EE, have a look at the overview page on my blog.

Have fun developing Jakarta EE CRUD API applications,

Phil

 

The post Jakarta EE 8 CRUD API Tutorial using Java 11 appeared first on rieckpil.


by rieckpil at January 19, 2020 03:07 PM

Hashtag Jakarta EE #3

by Ivar Grimstad at January 19, 2020 10:59 AM

Welcome to the third issue of Hashtag Jakarta EE!

Most of this week was spent at the Eclipse Foundation office in Ottawa. It is great to have the opportunity to meet the people I work with daily in person once in a while.

On Tuesday, January 14, there was an off-week MicroProfile Hangout dedicated to the discussions around the Working Group proposals for MicroProfile. The hangout was pretty well attended with the usual suspects doing most of the talking. See the presentation and meeting minutes for more details. The session was even recorded.

This week, we also had a Jakarta Tech talk by Adam Bien. He gave a great presentation about Jakarta EE application servers and Docker.

We even had a Jakarta EE Community Update Call where we talked about Jakarta EE 9, the Jakartification of the specification documents as well as the 2020 program and budget.

In the blog space, there is a lot being written about Jakarta EE. I will point to a couple of posts here. Will Lyons summarises The Jakarta EE 8 Community Retrospective and you can read about the approval of the Jakarta EE 9 release plan in Mike Milinkovich’ post Moving Forward with Jakarta EE 9,


by Ivar Grimstad at January 19, 2020 10:59 AM

Injecting List of Strings with MicroProfile Config

by admin at January 17, 2020 11:32 AM

A comma-separated String in microprofile-config.properties:


messages=hello,bye

...can be injected as a List of Strings (other types are injectable as well):

import java.util.List;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.eclipse.microprofile.config.inject.ConfigProperty;

@Path("messages")
public class MessagesResource {

    @Inject
    @ConfigProperty(name = "messages")
    List<String> messages;    

    @GET
    public List<String> messages() {
        return this.messages;
    }
}

The following command: curl -i localhost:8080/[THIN_WAR_NAME]/resources/messages prints: ["hello","bye"]

The 4kB ThinWAR project was created with Jakarta EE Essentials Archetype and deployed with: wad.sh in 1.9s


by admin at January 17, 2020 11:32 AM

Moving Forward With Jakarta EE 9

by Mike Milinkovich at January 16, 2020 05:06 PM

On behalf of the Jakarta EE Working Group, I am excited to announce the unanimous approval of the plan for Jakarta EE 9, with an anticipated mid-2020 release. Please note that the project team believes this timeline is aggressive, so think of this as a plan of intent with early estimate dates. The milestone dates will be reviewed and possibly adjusted at each release review.

If you have any interest at all in the past, present, or future of Java, I highly recommend that you read that plan document, as Jakarta EE 9 represents a major inflection point in the platform.

The key elements of  this Jakarta EE 9 release plan are to:

  • move all specification APIs to the jakarta namespace (sometimes referred to as the “big bang”);
  • remove unwanted or deprecated specifications;
  • minor enhancements to a small number of specifications;
  • add no new specifications, apart from specifications pruned from Java SE 8 where appropriate; and
  • Java SE 11 support.

What is not in the plan is the addition of any significant new functionality. That is because the goals of this Jakarta EE 9 release plan are to:

  • lower the barrier of entry to new vendors and implementations to achieve compatibility;
  • make the release available rapidly as a platform for future innovation; and
  • provide a platform that developers can use as a stable target for testing migration to the new namespace.

Moving a platform and ecosystem the size and scale of Jakarta EE takes time and careful planning. After a great deal of discussion the community consensus was that using EE 9 to provide a clear transition to the jakarta namespace, and to pare down the platform would be the best path to future success. While work on the EE 9 platform release is proceeding, individual component specification teams are encouraged to innovate in their individual specifications, which will hopefully lead to a rapid iteration towards the Jakarta EE 10 release.

Defining this release plan has been an enormous community effort. A lot of time and energy went into its development. It has been exciting to watch the … ummm passionate…. discussions evolve towards a pretty broad consensus on this approach. I would like to particularly recognize the contributions of Steve Millidge, Kevin Sutter, Bill Shannon, David Blevins, and Scott Stark for their tireless and occasionally thankless work in guiding this process.

The Jakarta EE Working Group has been busy working on creating a Program Plan, Marketing Plan and Budget for 2020. The team has also been very busy with creating a plan for the Jakarta EE 9 release. The Jakarta EE Platform project team, as requested, has delivered a proposal plan to the Steering Committee. With their endorsement, it will be voted on by the Specification Committee at their first meeting in January 2020.

Retrospective

The Jakarta EE 9 release is going to be an important step in the evolution of the platform, but it is important to recognize the many accomplishments that happened in 2019 that made this plan possible.

First, the Eclipse Foundation and Oracle successfully completed some very complex negotiations about how Java EE would be evolved under the community-led Jakarta EE process. Although the Jakarta EE community cannot evolve the specifications under the javax namespace, we were still able to fully transition the Java EE specifications to the Eclipse Foundation. That transition led to the second major accomplishment in 2019: the first release of Jakarta EE. Those two milestones were, in my view, absolutely key accomplishments. They were enabled by a number of other large efforts, such as creating the Eclipse Foundation Specification Process, significant revisions to our IP Policy, and establishing the Jakarta EE compatibility program. But ultimately, the most satisfying result of all of this effort is the fact that we have seven fully compatible Jakarta EE 8 products, with more on the way.

The Jakarta EE community was also incredibly active in 2019. Here are just a few of the highlights:

2019 was a very busy year, and it laid the foundation for a very successful 2020. I, and the entire Jakarta EE community, look forward to the exciting progress and innovation coming in 2020.


by Mike Milinkovich at January 16, 2020 05:06 PM

Jakarta EE + MicroProfile: Tips, Tricks and Workarounds--W-JAX Conference

by admin at January 16, 2020 03:52 AM

Jakarta EE + MicroProfile: Tips, Tricks and Workarounds (in German) W-JAX conference session:


by admin at January 16, 2020 03:52 AM

Using Jakarta Server Pages (JSP)s For Web Component Generation / Configuration

by admin at January 15, 2020 05:43 AM

JavaScript can be pre-generated on the backend and delivered as static content with JSPs. Jakarta Server Pages (JSP) are used in this screencast to configure a stage-dependent URI in a Web Component / Custom Element defined with MicroProfile Config and exposed via CDI:

The ThinWAR project was created with Jakarta EE Essentials Archetype, the 216kB ThinWAR (JS dependencies included) was built and deployed to Payara 5.193 #badassfish with: wad.sh in 3.2s


by admin at January 15, 2020 05:43 AM

Memory Consumption: WildFly Full ThinWAR vs. Quarkus SkimmedJAR

by admin at January 14, 2020 10:10 AM

Comparing the memory consumption of WildFly 18.0.1.Final (Java EE Full & Web Distribution) and Quarkus by deploying identical microprofile application to both runtimes:

The ThinWAR project was created with Jakarta EE Essentials Archetype, the 6kB ThinWAR was built and deployed with: wad.sh in 3.1s.

The Quarkus Runner 20.3kB "SkimmedJAR" was built in 4.3s from scratch. The file size of the native executable was 32 MB, the built took 53.7s.


by admin at January 14, 2020 10:10 AM

Summary of Community Retrospective on Jakarta EE 8 Release

by Will Lyons at January 13, 2020 09:42 PM

One of the topics we will cover at the Jakarta EE Update call on January 15 at 11:00 a.m. EST (please use this meeting ID) is a retrospective on the Jakarta EE 8 release that was conducted by the Jakarta EE Steering Committee.  The process included including solicitation of input from contributors to specifications, implementers of specifications, users of specifications and those observing from the outside.   The goal of the retrospective was to collect feedback on the Jakarta EE 8 delivery process that can be turned into action items to improve our delivery of subsequent releases, and enable as much of the community to participate as possible.

The full retrospective document is published here.   Some of the retrospective highlights include:

1) Areas that went well

  • Excellent progress after clearing legal hurdles
  • Excellent press and analyst coverage
  • Livestream and Code One announcements went well. 

2) Areas for improvement

  • Spec process and release management
    • Jakarta EE 8 seemed mostly Oracle driven.   Need more visible participation from others.
    • Need better documentation on the spec process and related processes
    • Need to reduce the number of meetings required to get out the next release
  • Communications
    • Need to communicate what we are doing and the progress we have made more.
    • Review the approach to Jakarta EE update calls
    • Need more even engagement via social media from all Strategic members.
  • Organization
    • Clarify the roles of the various committees
  • Other/general
    • We need to understand the outside view of the box we (the Jakarta EE/Eclipse Foundation) live in, and communicate accordingly.
    • Need a clear roadmap

3) In response to this feedback, the Steering Committee plans to take the following actions:

  • Proactive communication of CY2020 Jakarta EE Working Group Program Plan
    • This plan itself addresses much of the feedback above
    • Recommend sharing it now
    • Share budgets when confirmed/approved

We have followed up on topic during the December 11 Jakarta EE Update call.

  • Proactive communication of the Jakarta EE 9 release plan
    • Addresses some feedback on near term issues (e.g. move to jakarta namespace)
    • Should be placed in context of post Jakarta EE 9 goals
    • Participate in Jakarta EE update call on Nov 13 (planned)
    • Share when approved by Steering Committee

We are following up in all of these areas, both soliciting input and communicating through Jakarta EE Update calls.   We expect to announce formal approval for the prelease plan after this week’s Spec Committee meeting.

  • Proactive communication of significant Jakarta EE initiatives in general
    • Build into any significant planning event

We are building this into planning for JakartaOne Livestream Japan on Feb. 26, and Cloud Native for Java Day in Amsterdam on March 30.

  • Review approach to Jakarta EE Update calls (request Eclipse Foundation staff to drive review).

Your feedback on this topic is welcome – what do you want included in these calls?

  • Communication from Specification Committee on plan for addressing retrospective findings above after appropriate review and consensus.

The Spec Committee has not done an independent review per se, but are making a strong effort in conjunction with the Jakarta EE Platform Project to communicate proactively about the direction of Jakarta EE 9.   Look for more information on Jakarta EE 9 this week.

The process of responding to our experiences and feedback is ongoing.    We hope to continue to hear from you, so that we can continue to improve our release process for the community.

 

 

 


by Will Lyons at January 13, 2020 09:42 PM

Payara Platform 2019 Community Survey Results

by Debbie Hoffman at January 13, 2020 01:55 PM

We're proud to announce that our 2019 Community Survey results are now available! We conducted a survey between September and November 2019 to determine how organizations are using the Payara Platform and what ecosystem components are most commonly used with the platform. Thank you for contributing and helping us gain insight into which features and enhancements the community would most like to see in future releases of the Payara Platform.


by Debbie Hoffman at January 13, 2020 01:55 PM

New Features in Jersey Client

by Jan at January 13, 2020 09:29 AM

Jersey 2.30 comes with multiple new features, and this post describes three new interfaces on the client. They are PreInvocationInterceptor, PostInvocationInterceptor, and InvocationBuilderListener. Suppose a case that the start of the request is to be logged and even measured. This … Continue reading

by Jan at January 13, 2020 09:29 AM

Hashtag Jakarta EE #2

by Ivar Grimstad at January 12, 2020 10:59 AM

Welcome to the second issue of Hashtag Jakarta EE!

This week, I have been in Sandusky, Ohio for CodeMash. This awesome conference is organized by an Ohio Non-Profit Organization and is held at the Kalahari resort in Sandusky, Ohio.

In addition to meeting a bunch of awesome people, I had a talk about Eclipse MicroProfile.

Attending conferences like CodeMash that are not entirely Java-centric is a great reminder that outside our bubble, most developers haven’t heard about Jakarta EE or MicroProfile at all!

It is both challenging and rewarding to give a talk where you are not preaching to the choir. I encourage you all to do this more often. This is how we spread the message! This is how we grow our community!

In the Jakarta EE space, we started the week with an EE4J PMC meeting followed by the Jakarta EE Steering- and Specification committees. The most important agenda item discussed is the ongoing ballot for approval of the Jakarta EE 9 release plan in the Specification Committee. You can follow the ongoing ballot on the Jakarta EE Specification Committee mailing list.

At the end of last year, the Java EE Guardians completed their rebranding to become the Jakarta EE Ambassadors. I am really happy that I was able to help in the process of getting the new logo created. This is the first approved usage of the Jakarta EE brand and logo outside of the Jakarta EE Working Group. A milestone in itself!


by Ivar Grimstad at January 12, 2020 10:59 AM

Logging for JPA SQL queries with Wildfly

January 09, 2020 10:00 PM

Logging for real SQL queries is very important in case using any ORM solution, - as you never can be sure which and how many requests will send JPA provider to do find, merge, query or some other operation.

Wildfly uses Hibernate as JPA provider and provides few standard ways to enable SQL logging:

1. Add hibernate.show_sql property to your persistence.xml :

<properties>
    ...
    <property name="hibernate.show_sql" value="true" />
    ...
</properties>
INFO  [stdout] (default task-1) Hibernate: insert into blogentity (id, body, title) values (null, ?, ?)
INFO  [stdout] (default task-1) Hibernate: select blogentity0_.id as id1_0_, blogentity0_.body as body2_0_, blogentity0_.title as title3_0_ from blogentity blogentity0_ where blogentity0_.title=?

2. Enable ALL log level for org.hibernate category like:

/subsystem=logging/periodic-rotating-file-handler=sql_handler:add(level=ALL, file={"path"=>"sql.log"}, append=true, autoflush=true, suffix=.yyyy-MM-dd,formatter="%d{yyyy-MM-dd HH:mm:ss,SSS}")
/subsystem=logging/logger=org.hibernate.SQL:add(use-parent-handlers=false,handlers=["sql_handler"])
/subsystem=logging/logger=org.hibernate.type.descriptor.sql.BasicBinder:add(use-parent-handlers=false,handlers=["sql_handler"])
DEBUG [o.h.SQL] insert into blogentity (id, body, title) values (null, ?, ?)
TRACE [o.h.t.d.s.BasicBinder] binding parameter [1] as [VARCHAR] - [this is body]
TRACE [o.h.t.d.s.BasicBinder] binding parameter [2] as [VARCHAR] - [title]
DEBUG [o.h.SQL] select blogentity0_.id as id1_0_, blogentity0_.body as body2_0_, blogentity0_.title as title3_0_ from blogentity blogentity0_ where blogentity0_.title=?
TRACE [o.h.t.d.s.BasicBinder] binding parameter [1] as [VARCHAR] - [title]

3. Enable spying of SQL statements:

/subsystem=datasources/data-source=ExampleDS/:write-attribute(name=spy,value=true)
/subsystem=logging/logger=jboss.jdbc.spy/:add(level=DEBUG)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [DataSource] getConnection()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [Connection] prepareStatement(insert into blogentity (id, body, title) values (null, ?, ?), 1)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [PreparedStatement] setString(1, this is body)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [PreparedStatement] setString(2, title)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [PreparedStatement] executeUpdate()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [PreparedStatement] getGeneratedKeys()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] next()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] getMetaData()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] getLong(1)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] close()
...
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [DataSource] getConnection()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [Connection] prepareStatement(select blogentity0_.id as id1_0_, blogentity0_.body as body2_0_, blogentity0_.title as title3_0_ from blogentity blogentity0_ where blogentity0_.title=?)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [PreparedStatement] setString(1, title)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [PreparedStatement] executeQuery()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] next()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] getLong(id1_0_)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] wasNull()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] getString(body2_0_)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] wasNull()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] getString(title3_0_)
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] wasNull()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] next()
DEBUG [j.j.spy] java:jboss/datasources/ExampleDS [ResultSet] close()

So, from above we can see that variants 2 and 3 is most useful as allows to log queries with parameters. From other point of view - SQL logging can generate lot of unneeded debug information on production. To avoid garbage data in your log files, feel free to use Filter Expressions for Logging


January 09, 2020 10:00 PM

Jakarta EE Community Update January 2020

by Tanja Obradovic at January 09, 2020 02:26 PM

Welcome to our first update of 2020. As we start the new year, I want to wish you all the best. We have a lot to look forward to in 2020 as it will be the first year with multiple Jakarta EE releases. What a bright and optimistic way to start a new year!

As we ramp up our 2020 activities, here’s a look back at Jakarta EE highlights from the last few weeks in November and December of 2019. 

The Jakarta EE 8 Retrospective Is Complete

As we mentioned in our last update, the Jakarta EE Steering Committee asked the community to provide feedback on the Jakarta EE 8 release so we can make improvements in Jakarta EE 9 and future releases.

We’re happy to tell you that feedback has now been collected, analyzed, and summarized. 

To learn more about the results of the retrospective, keep an eye out for a blog post on the topic, but also, please join us for the January 15 at 11:00 a.m. EST using this meeting ID where this topic will be on the Agenda.

 The Jakarta EE 9 Release Plan Is Ready for Specification Committee Review

The Jakarta EE Platform Project team, led by Kevin Sutter and Steve Millidge, has been working very hard to create the detailed Jakarta EE 9 release plan. As promised, the plan has been created, presented, and endorsed by the Jakarta EE Steering Committee. The next step is for the Specification Committee to review it and vote on it early this year.

You can read the minutes of the Jakarta EE Platform Project team meetings here.

For the latest updates on Jakarta EE 9 release planning, listen to the recording of the December Jakarta EE update call here.

Reminder: We Need Your Help to Jakartify Specifications

Just a reminder that we now have the copyright for quite a number of Java EE specifications and we need the community to Jakartify them so they can be contributed to Jakarta EE.

To help you get started:

·      The Specification Committee has created a document that explains how to convert Java EE specifications to Jakarta EE.

·      Ivar Grimstad provided a demo during the community call in October. You can view it here.

And, here’s the list of specifications that are ready for the community to Jakartify.

• Jakarta Annotations

• Jakarta Enterprise Beans

• Jakarta Expression Language

• Jakarta Security

• Jakarta Server Faces

• Jakarta Interceptors

• Jakarta Authorization

• Jakarta Activation

• Jakarta Managed Beans

 

• Jakarta Deployment

• Jakarta XML RPC

• Jakarta Authentication

• Jakarta Mail

• Jakarta XML Binding

• Jakarta RESTful Web Services

• Jakarta Web Services Metadata

• Jakarta XML Web Services

• Jakarta Connectors

 

• Jakarta Persistence

• Jakarta JSON Binding

• Jakarta JSON Processing

• Jakarta Debugging Support for Other Languages

• Jakarta Server Pages

• Jakarta Transactions

• Jakarta WebSocket

 

Jakarta EE 2020 Marketing Plan Finalized

The Jakarta EE Marketing Operations Report for Q3 2019 was presented during the December Marketing Committee call. The report includes market activities and metrics for planned versus actual activities in Q3 and was generally well received by the committee.

You can read the meeting minutes here

Upcoming Events

Here’s a brief look at two upcoming Jakarta EE events to mark on your calendar:

·      JakartaOne Livestream – Japan, February 26

With the success of the JakartaOne Livestream event in September 2019, we’re expanding the initiative with more virtual conferences in more languages. Our next event is JakartaOne Livestream - Japan scheduled for February 26. Please follow the event on Twitter @JakartaOneJPN for all the details. Registration will open shortly. Keep in mind this entire event will be presented in Japanese.

·      Cloud Native for Java (CN4J) Day at KubeCon Amsterdam, March 30

CN4J day on March 30 is a full day (9:00 a.m.-5:00 p.m.) of expert talks, demos, and thought-provoking sessions focused on enterprise applications implemented using Jakarta EE and Eclipse MicroProfile on Kubernetes. This event is a great opportunity to meet with industry and community leaders, to better understand key aspects of Jakarta EE and MicroProfile technologies, and to share your ideas with ecosystem innovators. Learn more about the event here.

Join Community Update Calls

Every month, the Jakarta EE community holds a community call for everyone in the Jakarta EE community. For upcoming dates and connection details, see the Jakarta EE Community Calendar.

 Our next call is Wednesday, January 15 at 11:00 a.m. EST using this meeting ID.

We know it’s not always possible to join calls in real time, so here are links to the recordings and presentations:

·      The complete playlist.

·      December 11 call and presentation, featuring Steve Millage discussing Jakarta EE 9 release planning, an update on Jakartifying specifications from Ivar Grimstad, and a call for action to help with the Jakarta EE 2020 Program Plan and budget from Jakarta EE Steering Committee chair, Will Lyons.

November and December Event Summary

We ended a very exciting year for Jakarta EE by participating in three major events:  

·      Devoxx BE

·      KubeCon NA

·      Java2Days

We had members presenting at all three events and we’d like to sincerely thank them for their time and effort. A special shout-out to our Jakarta EE Developer Advocate, Ivar Grimstad, who presented multiple times and participated in a panel discussion at Java2Days.

Our members were also on hand at our booths at Devoxx BE and KubeCon NA to share their expertise, provide demos, and engage with attendees. Again, a huge thank you to everyone involved for their enthusiastic participation. Your engagement helps drive the success of the entire Jakarta EE community.

Stay Connected With the Jakarta EE Community

The Jakarta EE community is very active and there are a number of channels to help you stay up to date with all of the latest and greatest news and information. Tanja Obradovic’s blog summarizes the community engagement plan, which includes:

•  Social media: Twitter, Facebook, LinkedIn Group

•  Mailing lists: jakarta.ee-community@eclipse.org and jakarta.ee-wg@eclipse.org

•  Newsletters, blogs, and emails: Eclipse newsletter, Jakarta EE blogs, monthly update emails to jakarta.ee-community@eclipse.org, and community blogs on “how are you involved with Jakarta EE”

•  Meetings: Jakarta Tech Talks, Jakarta EE Update, Jakarta Town Hall, and Eclipse Foundation events and conferences

Subscribe to your preferred channels today. And, get involved in the Jakarta EE Working Group to help shape the future of open source, cloud native Java.

To learn more about Jakarta EE-related plans and check the date for the next Jakarta Tech Talk, be sure to bookmark the Jakarta EE Community Calendar.

 

 


by Tanja Obradovic at January 09, 2020 02:26 PM

Jersey Apache Connector Hangs …?

by Jan at January 07, 2020 09:59 PM

Jersey comes with various connectors to third-party HTTP clients. The way the connector is used is simple, put the connector and the third-party client to the classpath, and tell the client to use it. For Apache Connector, use: ClientConfig clientConfig … Continue reading

by Jan at January 07, 2020 09:59 PM

Deploy a Jakarta EE application to the root context

by rieckpil at January 07, 2020 06:24 AM

With the presence of Docker, Kubernetes and cheaper hardware, the deployment model of multiple applications inside one application server has passed. Now, you deploy one Jakarta EE application to one application server. This eliminates the need for different context paths.  You can use the root context / for your Jakarta EE application. With this blog post, you’ll learn how to achieve this for each Jakarta EE application server.

The default behavior for Jakarta EE application server

Without any further configuration, most of the Jakarta EE application servers deploy the application to a context path based on the filename of your .war. If you e.g. deploy your my-banking-app.war application, the server will use the context prefix /my-banking-app for your application. All you JAX-RS endpoints, Servlets, .jsp, .xhtml content is then available below this context, e.g /my-banking-app/resources/customers.

This was important in the past, where you deployed multiple applications to one application server. Without the context prefix, the application server wouldn’t be able to route the traffic to the correct application.

As of today, the deployment model changed with Docker, Kubernetes and cheaper infrastructure. You usually deploy one .war within one application server running as a Docker container. Given this deployment model, the context prefix is irrelevant. Mapping the application to the root context / is more convenient.

If you configure a reverse proxy or an Ingress controller (in the Kubernetes world), you are happy if you can just route to / instead of remembering the actual context path (error-prone).

Deploying to root context: Payara & Glassfish

As Payara is a fork of Glassfish, the configuration for both is quite similar. The most convenient way for Glassfish is to place a glassfish-web.xml file in the src/main/webapp/WEB-INF folder of your application:

<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN"
  "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
  <context-root>/</context-root>
</glassfish-web-app>

For Payara the filename is payara-web.xml:

<!DOCTYPE payara-web-app PUBLIC "-//Payara.fish//DTD Payara Server 4 Servlet 3.0//EN" "https://raw.githubusercontent.com/payara/Payara-Server-Documentation/master/schemas/payara-web-app_4.dtd">
<payara-web-app>
	<context-root>/</context-root>
</payara-web-app>

Both also support configuring the context path of the application within their admin console. IMHO this less convenient than the .xml file solution.

Deploying to root context: Open Liberty

Open Liberty also parses a proprietary web.xml file within src/main/webapp/WEB-INF: ibm-web-ext.xml

<web-ext
  xmlns="http://websphere.ibm.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd"
  version="1.0">
  <context-root uri="/"/>
</web-ext>

Furthermore, you can also configure the context of your application within your server.xml:

<server>
  <featureManager>
    <feature>servlet-4.0</feature>
  </featureManager>

  <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443"/>

  <webApplication location="app.war" contextRoot="/" name="app"/>
</server>

Deploying to root context: WildFly

WildFly also has two simple ways of configuring the root context for your application. First, you can place a jboss-web.xml within src/main/webapp/WEB-INF:

<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.4//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_4_0.dtd">
<jboss-web>
  <context-root>/</context-root>
</jboss-web>

Second, while copying your .war file to your Docker container, you can name it ROOT.war:

FROM jboss/wildfly
 ADD target/app.war /opt/jboss/wildfly/standalone/deployments/ROOT.war

For more tips & tricks for each application server, have a look at my cheat sheet.

Have fun deploying your Jakarta EE applications to the root context,

Phil

The post Deploy a Jakarta EE application to the root context appeared first on rieckpil.


by rieckpil at January 07, 2020 06:24 AM

Hashtag Jakarta EE #1

by Ivar Grimstad at January 05, 2020 10:59 AM

For a while now, I have been thinking of posting more regular updates about stuff going on in the Jakarta EE community. Kind of what Josh Long does with his “This Week in Spring” series. Being a big fan of Josh and the work he is doing in the community, I am not ashamed of copying him.

The goal is weekly updates, but being realistic I leave out the cadence from the title. So welcome to the first issue of Hashtag Jakarta EE!

The year 2020 is still young and pristine, most members enjoying a well-deserved vacation after a busy 2019.

Worth mentioning, though, is the ongoing discussion regarding the establishment of a Working Group for MicroProfile. There are currently two proposals on the table, the MicroProfile Working Group Proposal and the Cloud Native for Java Working Group Proposal.

At the end of last year, a release plan for Jakarta EE 9 was made available by the Jakarta EE Platform Project. The work with this release will start up again next week with weekly calls. These calls are open for anyone. The details can be found in the EE4J PMC Calendar.

Hope you enjoyed this short update!


by Ivar Grimstad at January 05, 2020 10:59 AM

2019 Summary

by Ivar Grimstad at December 31, 2019 10:48 AM

It is time for my yearly summary of conferences and community activities. In addition to numerous local meetups and online events, I had the opportunity to speak at the following major developer conferences:

Jfokus, Stockholm
Devnexus, Atlanta
ConFoo, Montreal
JavaLand, Brühl
JEEConf, Kiev
QCon, São Paulo
DevTalks, Bucharest
Java Cloud Africa, Johannesburg
J4K, Orlando
Oracle CodeOne, San Francisco
EclipseCon Europe, Ludwigsburg
Trondheim Developer Day, Trondheim
Devoxx Ukraine, Kiev
Devoxx Belgium, Antwerp
Devoxx Morocco, Agadir
Java2Days, Sofia

The biggest change for me this year happened in October when I joined the Eclipse Foundation as the Jakarta EE Developer Advocate. This means that I am able to dedicate all my time to community building and contributions to open source.

My new role enable me to be even more present at conferences and events around the World, so I expect 2020 to be at least as busy. I already have conferences lined up for the first quarter and more in the planning.

With Jakarta EE 8 out the door in 2019, we are now in full planning for Jakarta EE 9. The biggest impact of this release will be the namespace change from javax.* to jakarta.*. We will also prune some not very widely used technologies in order to lighten the burden for new implementations of the platform. This work will probably continue in subsequent releases.

All in all 2019 was a great year for Jakarta EE and I expect 2020 to be even better!


by Ivar Grimstad at December 31, 2019 10:48 AM

Why Jakarta EE beats other java solutions from security point of view

December 26, 2019 10:00 PM

No one care about security until security incident. In case enterprise development last one can costs too much, so any preventive steps can help. Significant part part of the OWASP Application Security Verification Standard (ASVS) reads:

10.2.1 Verify that the application source code and third party libraries do not contain unauthorized phone home or data collection capabilities. Where such functionality exists, obtain the user's permission for it to operate before collecting any data.
10.2.3 Verify that the application source code and third party libraries do not contain back doors, such as hard-coded or additional undocumented accounts or keys, code obfuscation, undocumented binary blobs, rootkits, or anti-debugging, insecure debugging features, or otherwise out of date, insecure, or hidden functionality that could be used maliciously if discovered.
10.2.4 Verify that the application source code and third party libraries does not contain time bombs by searching for date and time related functions.
10.2.5 Verify that the application source code and third party libraries does not contain malicious code, such as salami attacks, logic bypasses, or logic bombs.
10.2.6 Verify that the application source code and third party libraries do not contain Easter eggs or any other potentially unwanted functionality.
10.3.2 Verify that the application employs integrity protections, such as code signing or sub-resource integrity. The application must not load or execute code from untrusted sources, such as loading includes, modules, plugins, code, or libraries from untrusted sources or the Internet.
14.2.4 Verify that third party components come from pre-defined, trusted and continually maintained repositories.

In other words that meaning you should: "Verify all code including third-party binaries, libraries, frameworks are reviewed for hardcoded credentials (backdoors)."

In case development according to Jakarta EE specification you shouldn't be able to use poor controlled third party libraries, as all you need already came with Application Server. In turn, last one is responsible for in time security updates, ussage of verified libraries and many more...


December 26, 2019 10:00 PM

How to setup Darcula LAF on Netbeans 11

December 25, 2019 10:00 PM

It is pity, but Apache Netbeans IDE still comes without support default dark mode. Enabling Netbeans 8.2 Plugin portal does not have any effect, so to use plugins from previous versions we need to add New Provider (Tools->Plugins) with next URL:

http://plugins.netbeans.org/nbpluginportal/updates/8.2/catalog.xml.gz

add provider

After that you should be able setup Darcula LAF in standard way

add provider


December 25, 2019 10:00 PM

Java ile Özel Notasyon Geliştirimi

by Hüseyin Akdogan at December 23, 2019 06:00 AM

JDK 1.5 ve üstü bir sürümle geliştirim yapmış her seviyeden Java geliştiricisi notasyon kullanmıştır. @Inject, @Entity, @Autowired, hiç olmadıysa @Override notasyonunu görmemiş, kullanmamış herhalde yoktur. Java dilinin güçlü yanlarından biri olan notasyonlar, birer dekoratör gibi çalışarak; sınıf, yapılandırıcı, metot, alan gibi program yapılarına meta verisi eklememizi sağlar. Geliştiriciye belirli bir eylem/davranışı adeta markalayıp, uygulamanın ihtiyaç duyulan noktalarına enjekte etme olanağı sağlayan notasyonlar, mükerrer kod yazımını azaltıp, kod okunurluğunu artırırlar.

Notasyonların gücünden, Java geliştiricileri kendi özel notasyonlarını oluşturarak yeterince yararlanmakta mıdır? Başta kendi geliştirim tecrübem olmak üzere kişisel gözlemim ve çeşitli yazı, makale, yayınlanmış anketlerden anladığım; Javacılar notasyon kullanmayı yazmaktan daha çok seviyor. Bu yazıyla amacım, notasyonları daha yakından tanımanıza yardımcı olmak, çalışma mantıklarını göstermek ve basit bir örnek aracılığıyla kendi notasyonunuzu nasıl yazıp kullanabileceğinizi örneklendirerek, özel notasyonların sağladığı avantajlara dikkatinizi çekmek.

Nasıl Çalışıyor?

An annotation is a marker which associates information with a program construct, but has no effect at run time. JLS Section 9.7

Java dil belirtiminde ifade edildiği gibi, notasyonlar kendi başlarına çalışma zamanında herhangi bir etkiye sahip değildir. Daha açık bir ifadeyle, bir notasyon tek başına eklendiği programın çalışma zamanı davranışını değiştirmez.Aslında bir notasyon, uygulandığı noktada elde edilmek istenen davranışı bildiren bir işaretçi(an annotation is a marker – JSL) gibi davranır. Bu sebeple, notasyonların geliştirici tarafından belirlenmiş davranış/eylemi gerçekleştirmesi için çalışma zamanı çerçeveleri(runtime frameworks) veya derleyici tarafından işlenmesi gerekir. Notasyonlar, derleme zamanında Java derleyicisinin bir tür eklentisi sayılabilecek notasyon işleyiciler(annotation processors), çalışma zamanında ise Java Reflection API tarafından işlenir. Bu yazıda, çalışma zamanında Reflection API ile işlenecek bir notasyon örneğini inceleyeceğiz.

Nasıl Tanımlanır?

Bir notasyon tanımlamak, arayüz tanımlamaya benzer. Sözdizimsel fark, interface anahtarı başına @ sembolünün getirilmesinden ibarettir.

public @interface Monitor {}

Bir notasyon oluşturmak için temelde iki bilgiyi sağlamak gerekmektedir. Bunlardan biri Retention politikası, diğeri Target. Retention politikası, notasyona erişim zamanını tanımlarken, target hangi yapıya(sınıf, method, alan) uygulanacağını tanımlamaktadır.

Retention politikası, RetentionPolicy ile tanımlanır. RetentionPolicy enum tipinde bir veri yapısıdır ve java.lang.annotation paketi altında bulunmaktadır.

package java.lang.annotation;
/**
* Annotation retention policy.  The constants of this enumerated type
* describe the various policies for retaining annotations.  They are used
* in conjunction with the {@link Retention} meta-annotation type to specify
* how long annotations are to be retained.
*
* @author  Joshua Bloch
* @since 1.5
*/
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time.  This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}

Görüldüğü üzere 3 retention politikası vardır.

  • SOURCE: Notasyon derleyici tarafından atılır.
  • CLASS: Notasyon derleyici tarafından oluşturulan sınıf dosyasına kaydedilir ve JVM tarafından saklanması gerekmez. Varsayılan davranış biçimidir.
  • RUNTIME: Notasyon sınıf dosyasına derleyici tarafından kaydedilir ve çalışma zamanında JVM tarafından saklanır, böylece reflection ile okunabilir.

Runtime, uygulamaların notasyonlara ve ilişkili verilerine reflection ile erişip kod yürütülmesine izin verdiği için en bilinen ve yaygın olarak kullanılan retention politikasıdır.

Java 9 sonrası, 11 target vardır; bir başka deyişle 11 yapıya notasyon uygulayabiliriz.

  • TYPE: Sınıf, arayüz, notasyon, enum gibi tipleri hedefler
  • FIELD: Sınıf değişkenleri, enum sabitleri gibi alan tiplerini hedefler
  • METHOD: Sınıf metotlarını hedefler
  • MODULE: Java 9 ile gelmiştir, modülleri hedefler
  • PARAMETER: Metot, yapılandırıcı parametrelerini hedefler
  • CONSTRUCTOR: Yapılandırıcıları hedefler
  • LOCAL_VARIABLE: Yerel değişkenleri hedefler
  • ANNOTATION_TYPE: Notasyonları hedefler ve başka bir notasyon ekler
  • PACKAGE: Paketleri hedefler
  • TYPE_PARAMETER: Java 1.8 ile gelmiştir, MyClass<T>’deki T gibi jenerik parametreleri hedefler
  • TYPE_USE: Java 1.8 ile gelmiştir, herhangi bir türün kullanımını(örneğin new ile oluşturulma, arayüz implementasyonu, cast işlemi vb) hedefler

Notasyon Parametreleri ve Notasyon Tipleri

Notasyonlar program yapılarına meta verisini, parametreleri aracılığıyla ekler. Bir notasyonun parametreye sahip olup olmaması tipini belirler. Parametre bildirimi içermeyen notasyonlar işaretçi notasyon(marker annotation type) türünü, tek bir parametre bildirimi içeren notasyonlar tek elemanlı(single element annotation type), birden fazla parametre bildirimi içeren notasyonlar ise kompleks notasyon(complex annotation type) türünü oluşturur. Primitif tipler, String, Class, Enum, bir başka notasyon ve bu anılan tiplerin dizi tipi, bir notasyon parametresi olarak bildirilebilir.

Senaryomuz

Profiling için kodumuzda çalışma sürelerini ölçmek istediğimiz metotlara sahip olduğumuzu düşünelim. Her metodun değil, bazı metotların çalışma süresini ölçmek istiyoruz; üstelik bu metotlara ilerde yenileri eklenebilir. Bunun için bir notasyon yazmak iyi bir fikirdir çünkü en başta belirttiğimiz üzere kod okunurluğunu bozmadan ek olarak aynı davranışı tekrar tekrar dilediğimiz noktalarda(örneğin kodumuza eklenecek yeni metotlarda) elde etmek için notasyonlar biçilmiş kaftandır.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Monitor
{
MonitorPolicy value();
}

Retention policy ve Target’tan daha önce bahsettiğimiz için, yukarıda görülen notasyonun çalışma zamanında Reflection API ile işlenebileceğini ve ancak metotlara(başka bir yapıya uygulanırsa derleme zamanında hata alınır) uygulanabileceğini kestirmeniz zor değil. Bu noktada Target ile ilgili şu detayı da paylaşalım, birden fazla hedef tanımlayabilirsiniz.

@Target({ElementType.FIELD, ElementType.METHOD})

Notasyonumuzun gövdesinde ise enum tipinde MonitorPolicy parametresinin deklare edildiğini görüyorsunuz. İlgili enum değerine çalışma zamanında value() metodu üzerinden erişeceğimiz gibi, notasyonumuza değer geçirmek için value’yu anahtar olarak da kullanabiliriz.

@Monitor(value = MonitorPolicy.SHORT)

Fakat değer geçirmek için value anahtarını kullanmak zorunlu değildir. Aşağıdaki kullanım ile yukarıdaki eşdeğerdir.

@Monitor(MonitorPolicy.SHORT)

Value dışında farklı bir ismi kullansaydık bunu belirtmemiz gerekirdi çünkü value, notasyonlarda varsayılan anahtar ismidir. MonitorPolicy SHORT ve DETAILED değerlerine sahiptir. Bu değerlerle, çalışma süresini ölçeceğimiz metotlara dair döndürülecek bilginin biçimini belirliyoruz, ayrıntılı veya kısa.

enum MonitorPolicy 
{
SHORT,DETAILED
}

Tanımladığımız parametreye varsayılan bir değer atamak istediğimizde ise default anahtarını kullanırız.

MonitorPolicy value() default MonitorPolicy.SHORT;

Bu durumda aşağıdaki gibi bir kullanımda, monitor policy short olacaktır.

@Monitor
public String getUserInfo(){
   //Make HTTP request
}

İşleyicimiz

Daha önce ifade ettiğimiz gibi, notasyonlar kendi başlarına herhangi bir kod çalıştırmazlar. Monitor notasyonunda Retention policy olarak RUNTIME tanımlandığı için, çalışma zamanında Java Reflection API kullanılarak işlenmesi gerekir. Aşağıdaki metot bu vazifeyi gerçekleştirir.

public static String executor(final Object object, final Object... passedParameters) {
    checkObjectReference(object);
    final StringBuilder result = new StringBuilder();
    final Method[] methods = object.getClass().getDeclaredMethods();
    for(Method method :methods){
        if(method.isAnnotationPresent(Monitor.class)){
            if(passedParameters.length > 0){
                result.append(invoker(method, object, passedParameters));
            } else {
                result.append(invoker(method, object));
            }
        }
    }
    return result.toString();
}

Executor metodu, biri Monitor notasyonunu kullanan sınıf referansı, diğeri varargs tipinde; ölçüm yapılacak metotların parametreleri olmak üzere 2 argüman alıyor.

Önce object referansı üzerinden, ilgili nesnenin deklare edilmiş metotlarını çekip ardından bir döngü yardımıyla gezilen metotlarda Monitor notasyonunun uygulanıp uygulanmadığını Reflection API’ye ait isAnnotationPresent()metoduyla(metoda notasyon nesnesini geçirdiğimize dikkat edin) kontrol ediyoruz. Monitor notasyonunu uygulayan metod varsa, koşturulması için invoker metodunu çağırıyoruz.

private static String invoker(final Method method, Object object, Object... passedParameters) {

    method.setAccessible(true);
    final StringBuilder result = new StringBuilder();
    final MonitorPolicy policy = method.getAnnotation(Monitor.class).value();
    long start = System.currentTimeMillis();

    try {
        if (passedParameters.length > 0) {
            checkTypeMismatch(method.getName(), method.getParameters(), passedParameters);
            method.invoke(object, passedParameters);
        } else if(method.getGenericParameterTypes().length > 0){
            throw new MissingArgumentException("The parameter(s) of the " + method.getName() + " method are missing");
        } else {
            method.invoke(object);
        }

        final long end = System.currentTimeMillis();
        if(policy.equals(MonitorPolicy.SHORT)){
            result.append(end - start).append(" ms");
            logger.info( "{} ms", (end - start));
        } else {
            result.append("Total execution time of ")
                    .append(method.getName())
                    .append(" method is ")
                    .append(end - start)
                    .append(" ms");
            logger.info("Total execution time of {} method is {} ms",  method.getName(), (end - start));
        }

    } catch ...

Public olarak deklare edilmemiş metotlara da erişebilmek için, invoker metodunda ilk olarak method.setAccessible(true); ile erişim kontrolünü yapılandırıyoruz; aksi halde private metotlar için IllegalAccessException istisnasıyla karşılaşırız. Sonraki adımda, çağırıldığı yapıyla(bizim örneğimizde metot) ilişkilendirilmiş, belirtilen tipteki(metoda notasyon nesnesini geçirdiğimize dikkat edin) notasyonu döndüren Reflection API’ye ait getAnnotation metodunu kullanarak, notasyonumuzda tanımlanmış değeri çekiyoruz. Bu değeri, çalışma süresine dair bilgiyi çıktılama biçimizi belirlemede kullanacağız. Bu aşamadan sonra, o anki zaman mührünü milisaniye cinsinden start değişkeninde depoluyoruz; Monitor notasyonunu uygulamış metodu, Reflection API’nin invoke metoduyla koşturduktan sonra elde edilen zaman mührünü ise end değişkeninde. Son aşamada ise, MonitorPolicy’ye bağlı olarak çalışma süresini çıktılıyoruz.

Aşağıda, paylaşılan örnekteki gibi bir kullanımda alacağımız muhtemel çıktıyı görüyorsunuz.

@Monitor(MonitorPolicy.DETAILED)
public String getUserInfo(){
   //Make HTTP request
}
Profiler.executor(new User());

Total execution time of getUserInfo method is 1459 ms

Monitor notasyonunu içeren uygulamaya buradan ulaşabilirsiniz.

Sonuç

Java notasyonları sınıf, yapılandırıcı, metot, alan gibi Java program yapılarına meta verisi eklememizi sağlayan, bu şekilde mükerrer kod yazımını azaltıp, kod okunurluğunu artıran Java dilinin güçlü yanlarından biridir. Notasyonlar kendi başlarına herhangi bir kod çalıştırmazlar, bunun yerine derleyici veya ait oldukları çerçeve(framework) için, uygulandığı noktada elde edilmek istenen davranışı bildiren bir işaretçi gibi davranıp, derleme zamanında Java Annotation Processors’ler, çalışma zamanında ise Java Reflection API tarafından işlenirler.


by Hüseyin Akdogan at December 23, 2019 06:00 AM

Run your Jakarta EE/MicroProfile application on Quarkus with minimum changes

by Jean-François James at December 17, 2019 04:58 PM

Quarkus 1.0.0.Final has been released, so I think it’s time to go beyond the “Get started” guides and to give it a try. In this article, I’m going to illustrate how to run an existing Jakarta EE/MicroProfile application on Quarkus, both in JVM and native modes, with minimum changes on the code and the configuration. I’ve […]

by Jean-François James at December 17, 2019 04:58 PM

The Payara Monthly Catch for Nov/Dec 2019

by Jadon Ortlepp (Jadon.Ortlepp@Payara.fish) at December 17, 2019 10:30 AM

For the festive season we decided to change it up abit and create a mega bumper edition of the month catch by combining November and December and serve it to you before many head off for their Christmas holidays. 

Below you will find a curated list of some of the most interesting news, articles and videos from this month. Cant wait until the end of the month? then visit our twitter page where we post all these articles as we find them! 


by Jadon Ortlepp (Jadon.Ortlepp@Payara.fish) at December 17, 2019 10:30 AM

Jakarta EE: Creating an Enterprise JavaBeans Timer

by Rhuan Henrique Rocha at December 17, 2019 03:33 AM

Enterprise JavaBeans (EJB) has many interesting and useful features, some of which I will be highlighting in this and upcoming articles. In this article, I’ll show you how to create an EJB timer programmatically and with annotation. Let’s go!

The EJB timer feature allows us to schedule tasks to be executed according a calendar configuration. It is very useful because we can execute scheduled tasks using the power of Jakarta context. When we run tasks based on a timer, we need to answer some questions about concurrency, which node the task was scheduled on (in case of an application in a cluster), what is the action if the task does not execute, and others. When we use the EJB timer we can delegate many of these concerns to Jakarta context and care more about business logic. It is interesting, isn’t it?

Creating an EJB timer programmatically

We can schedule an EJB timer to runs according to a business logic using a programmatic approach. This method can be used when we want a dynamic behavior, according to the parameter values passed to the process. Let’s look at an example of an EJB timer:

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import java.util.logging.Logger;

@Stateless
public class MyTimer {

    private Logger logger = Logger.getLogger(MyTimer.class.getName());
    @Resource
    private SessionContext context;

    public void initTimer(String message){
        context.getTimerService().createTimer(10000, message);
    }

    @Timeout
    public void execute(){
        logger.info("Starting");

        context.getTimerService().getAllTimers().stream().forEach(timer -> logger.info(String.valueOf(timer.getInfo())));
        

        logger.info("Ending");
    }    
}

To schedule this EJB timer, call this method:

@Inject
private MyTimer myTimer;
....
myTimer.initTimer(message);

After passing 10000 milliseconds, the method annotated with @Timeout will be called.

Scheduling an EJB timer using annotation

We can also create an EJB timer that is automatically scheduled to run according to an annotation configuration. Look at this example:

@Singleton
public class MyTimerAutomatic {

    private Logger logger = Logger.getLogger(MyTimerAutomatic.class.getName());

    @Schedule(hour = "*", minute = "*",second = "0,10,20,30,40,50",persistent = false)
    public void execute(){

        logger.info("Automatic timer executing");

    }
}

As you can see, to configure an automatic EJB timer schedule, you can annotate the method using @Schedule and configure the calendar attributes. For example:

@Schedule(hour = "*", minute = "*",second = "0,10,20,30,40,50",persistent = false)

As you can see, the method execute is configured to be called every 10 seconds. You can configure whether the timer is persistent as well.

Conclusion

EJB timer is a good EJB feature that is helpful in solving many problems. Using the EJB timer feature, we can schedule tasks to be executed, thereby delegating some responsibilities to Jakarta context to solve for us. Furthermore, we can create persistent timers, control the concurrent execution, and work with it in a clustered environment.  If you want to see the complete example, visit this repository on GitHub.

This post was released at Developer Red Hat blog and you can see here.

 


by Rhuan Henrique Rocha at December 17, 2019 03:33 AM

Jakarta EE Quickstart Guides for each application server

by rieckpil at December 16, 2019 03:08 PM

Read about my latest YouTube series: Jakarta EE Quickstart Guides. It targets both Jakarta EE newcomers and experienced developers to provide tutorials for common tasks. This page works as an entry page to query for the tutorial you are looking for.

About the Jakarta EE Quickstart Guides series

Jakarta EE Quickstart Guides Blog Logo

The goal of this series is to provide short (5 to 15 minutes) and easy-to-understand videos on YouTube for common  Jakarta EE topics. Next to the videos, I’m uploading the source code for the examples on GitHub.

Furthermore, I’ll use all compatible Jakarta EE application server for these guides to vary and fulfill everyone’s needs.

» Jakarta EE Quickstart Guides YouTube Playlist

I. Jakarta EE project setup

II. Jakarta EE tooling

III. Resource connection quickstart guides

IV. Testing a Jakarta EE project

V. Development

VI. more to come

There are more topics to come, e.g.: integration with Eclipse MicroProfile, deployment to Kubernetes, best practices, etc.

Further Jakarta EE resources

The Jakarta EE guide you are searching for is missing?

I’m looking forward to creating a quick start guide for your topic. Either add a comment to an existing video on YouTube or create an issue on the corresponding GitHub repository.

Furthermore, have a look at all Jakarta EE Tutorials on my blog for more content about Jakarta EE.

Have fun with these Jakarta EE Tutorials,

Phil

The post Jakarta EE Quickstart Guides for each application server appeared first on rieckpil.


by rieckpil at December 16, 2019 03:08 PM

Jakarta EE & React file up- and download using Java 11 and TypeScript

by rieckpil at December 12, 2019 05:55 AM

Given the latest release of Payara, we can now officially use it with Java 11 and Jakarta EE. I’m using this occasion to demonstrate how to create a Jakarta EE backend with a React frontend using TypeScript to up- and download a file. This example also includes a solution to create and bundle a React application with Maven and serve the result with Payara.

The final result will look like the following:

Jakarta EE React File application

Jakarta EE project setup

The sample project uses Maven, Java 11 and the following dependencies:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>de.rieckpil.blog</groupId>
  <artifactId>jakarta-ee-react-file-handling</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <failOnMissingWebXml>false</failOnMissingWebXml>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <jakarta.jakartaee-api.version>8.0.0</jakarta.jakartaee-api.version>
    <jersey.version>2.29.1</jersey.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>jakarta.platform</groupId>
      <artifactId>jakarta.jakartaee-api</artifactId>
      <version>${jakarta.jakartaee-api.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-multipart</artifactId>
      <version>${jersey.version}</version>
      <scope>provided</scope>
    </dependency><dependency>
      <groupId>org.glassfish.jersey.core</groupId>
      <artifactId>jersey-server</artifactId>
      <version>${jersey.version}</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  
  <!-- more -->
</project>

As the JAX-RS specification does not provide a standard for handling file upload as multipart data, I’m including proprietary Jersey dependencies for this. We can mark them with scope provided, as they are bundled with Payara and therefore don’t need to be part of the .war file.

For this project, I’ll demonstrate a solution to build the frontend application with Maven. Furthermore, the Payara Server will then serve the static files for the Single Page Application. We can achieve this while configuring the build section of our project:

<project>

  <!-- dependencies like seen above -->

  <build>
    <finalName>jakarta-ee-react-file-handling</finalName>
    <plugins>
      <plugin>
        <groupId>com.github.eirslett</groupId>
        <artifactId>frontend-maven-plugin</artifactId>
        <version>1.8.0</version>
        <executions>
          <execution>
            <id>install node and npm</id>
            <goals>
              <goal>install-node-and-npm</goal>
            </goals>
            <phase>generate-resources</phase>
          </execution>
          <execution>
            <id>npm install</id>
            <goals>
              <goal>npm</goal>
            </goals>
            <phase>generate-resources</phase>
            <configuration>
              <arguments>install</arguments>
            </configuration>
          </execution>
          <execution>
            <id>npm test</id>
            <goals>
              <goal>npm</goal>
            </goals>
            <phase>generate-resources</phase>
            <configuration>
              <environmentVariables>
                <CI>true</CI>
              </environmentVariables>
              <arguments>test</arguments>
            </configuration>
          </execution>
          <execution>
            <id>npm build</id>
            <goals>
              <goal>npm</goal>
            </goals>
            <phase>generate-resources</phase>
            <configuration>
              <environmentVariables>
                <CI>true</CI>
              </environmentVariables>
              <arguments>run build</arguments>
            </configuration>
          </execution>
        </executions>
        <configuration>
          <workingDirectory>src/main/frontend</workingDirectory>
          <nodeVersion>v12.13.1</nodeVersion>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
      </plugin>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.22.2</version>
      </plugin>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.3</version>
        <configuration>
          <webResources>
            <resource>
              <directory>${project.basedir}/src/main/frontend/build</directory>
            </resource>
          </webResources>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

First, the frontend-maven-plugin takes care of installing all npm dependencies, executing the frontend tests and building the React Single Page Application.  It also downloads (if not already present) the correct Node version. You can configure this with nodeVersion in the configuration section of the plugin. This will ensure each team member uses the same version to build the project.

The CI=true is specific for create-react-app. This will ensure to not run the tests and the frontend build in interactive mode and rather finish the process to proceed further Maven plugins.

Finally, we can configure the maven-war-plugin to include our frontend resources as web resources. When we now build the project with mvn package, it will build the frontend and backend application and bundle the frontend resources within our .war file.

Handling files with the Jakarta EE backend

Next, let’s have a look at how to handle the file up- and download with our Jakarta EE backend. The backend provides two endpoints: one to upload a file and another to download a random file.

In the first place, we have to register the MultiPartFeature of Jersey for our application. There are multiple ways to do this. I’m using a JAX-RS configuration class to achieve this:

@ApplicationPath("resources")
public class JAXRSConfiguration extends ResourceConfig {
  public JAXRSConfiguration() {
    packages("de.rieckpil.blog").register(MultiPartFeature.class);
  }
}

As a result of this, we can now use the proprietary Jersey feature for our JAX-RS resource.

For the file upload, we’ll store the file in a list and include the original filename:

@Path("files")
@ApplicationScoped
public class FileResource {

  private List<FileContent> inMemoryFileStore = new ArrayList();

  @POST
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  public Response uploadNewFile(@FormDataParam("file") InputStream inputStream,
                                @FormDataParam("file") FormDataContentDisposition fileDetails,
                                @Context UriInfo uriInfo) throws IOException {

    this.inMemoryFileStore.add(new FileContent(fileDetails.getFileName(), inputStream.readAllBytes()));

    return Response.created(uriInfo.getAbsolutePath()).build();
  }
}

The FileContent class is a simple POJO to store the relevant information:

public class FileContent {

  private String fileName;
  private byte[] content;

  // constructors, getters & setters
}

Our frontend application can request a random file on the same endpoint but has to use HTTP GET. To properly download a file, we have to set the content type to application/octet-stream and configure some HTTP headers:

@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadRandomFile() {

  if (inMemoryFileStore.size() == 0) {
    return Response.noContent().build();
  }

  FileContent randomFile = inMemoryFileStore.get(
    ThreadLocalRandom.current().nextInt(0, inMemoryFileStore.size()));

  return Response
    .ok(randomFile.getContent())
    .type(MediaType.APPLICATION_OCTET_STREAM)
    .header(HttpHeaders.CONTENT_LENGTH, randomFile.getContent().length)
    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + randomFile.getFileName())
    .build();
}

React project setup

Next, let’s have a look at the React project setup. With create-react-app we have a great solution for bootstrapping new React applications. I’m using this to place the frontend within the src/main folder with the following command:

npx create-react-app frontend --template typescript

To actually create a TypeScript based project, we can use the argument --template typescript.

For proper components and styling, I’m adding semantic-ui-react and semantic-ui-css to this default project:

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "@types/jest": "^24.0.23",
    "@types/node": "^12.12.14",
    "@types/react": "^16.9.15",
    "@types/react-dom": "^16.9.4",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-scripts": "3.3.0",
    "semantic-ui-css": "^2.4.1",
    "semantic-ui-react": "^0.88.2",
    "typescript": "^3.7.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

File up- and download from React

Finally, let’s have a look at React application written in TypeScript. It contains three components: FileUploadComponent, FileDownloadComponent, and App to wrap everything. All of these are using React’s functional component approach.

Let’s start with the FileUploadComponent:

interface FileUploadComponentProps {
  uploadFile: (file: File) => void
}

const FileUploadComponent: React.FC<FileUploadComponentProps> = ({uploadFile}) => {

  const [fileContent, setFileContent] = useState<File | null>();

  return <React.Fragment>
    <Header as='h4'>Upload your file</Header>
    <Form onSubmit={event => fileContent && uploadFile(fileContent)}>
      <Form.Group widths='equal'>
        <Form.Field>
          <input placeholder='Select a file'
                 type='file'
                 onChange={event => event.target.files && setFileContent(event.target.files.item(0))}/>
        </Form.Field>
        <Button type='submit'>Upload</Button>
      </Form.Group>
    </Form>
  </React.Fragment>;
};

export default FileUploadComponent;

Once we upload a file and submit the HTML form, the component will pass the uploaded file to the uploadFile function.

The FileDownloadComponent is even simpler, as it executes a download function whenever someone clicks the button:

interface FileDownloadComponentProps {
  downloadFile: () => void
}

const FileDownloadComponent: React.FC<FileDownloadComponentProps> = ({downloadFile}) => {
  return <React.Fragment>
    <Header as='h4'>Download a random file</Header>
    <Form>
      <Button type='submit' onClick={downloadFile}>Download</Button>
    </Form>
  </React.Fragment>;
};

export default FileDownloadComponent;

Last but not least the App component orchestrates everything:

const App: React.FC = () => {

  const [statusInformation, setStatusInformation] = useState<StatusInformation>();

  return <Container text style={{marginTop: 10}}>
    <Image src='/jakartaEELogo.png' size='small' centered/>
    <Header as='h2' textAlign='center'>Jakarta EE & React File Handling</Header>
    {statusInformation && <Message color={statusInformation.color}>{statusInformation.message}</Message>}
    <FileUploadComponent uploadFile={file => {
      setStatusInformation(undefined);
      new ApiClient()
        .uploadFile(file)
        .then(response => setStatusInformation(
          {
            message: 'Successfully uploaded the file',
            color: 'green'
          }))
        .catch(error => setStatusInformation({
          message: 'Error occurred while uploading file',
          color: 'red'
        }))
    }}/>
    <Divider/>
    <FileDownloadComponent
      downloadFile={() => {
        setStatusInformation(undefined);
        new ApiClient()
          .downloadRandomFile()
          .then(response => {
            setStatusInformation({
              message: 'Successfully downloaded a random file',
              color: 'green'
            });
            downloadFileInBrowser(response);
          })
          .catch(error => setStatusInformation({
            message: 'Error occurred while downloading file',
            color: 'red'
          }))
      }}/>
  </Container>;
};

export default App;

Our ApiClient uses the fetch API for making HTTP requests:

export class ApiClient {

  uploadFile(file: File) {
    let data = new FormData();
    data.append('file', file);

    return fetch('http://localhost:8080/resources/files', {
      method: 'POST',
      body: data
    });
  }

  downloadRandomFile() {
    return fetch('http://localhost:8080/resources/files');
  }
}

To actually download the incoming file from the backend directly, I’m using the following solution:

const downloadFileInBrowser = (response: Response) => {
  const filename = response.headers.get('Content-Disposition')!.split('filename=')![1];
  response.blob().then(blob => {
    let url = window.URL.createObjectURL(blob);
    let a = document.createElement('a');
    a.href = url;
    a.download = filename;
    a.click();
  });
};

File handling for other project setups

Similar to this example, I’ve created several guides for handling files with different project setups. Besides Jakarta EE and React file handling, find other examples here:

The source code, with instructions on how to run this example, is available on GitHub.

Have fun up- and downloading files with Jakarta EE and React,

Phil

The post Jakarta EE & React file up- and download using Java 11 and TypeScript appeared first on rieckpil.


by rieckpil at December 12, 2019 05:55 AM

The Road to Jakarta EE Compatibility

by Patrik Duditš at December 11, 2019 06:06 PM

Payara Platform 5.194 was released recently, and just like the previous release, it is a certified Jakarta EE implementation. The request for certification can be seen on Jakarta EE platform project issue tracker.


by Patrik Duditš at December 11, 2019 06:06 PM

Jakarta EE 9 Shaping Up

by Ivar Grimstad at December 06, 2019 04:09 PM

The Jakarta EE Platform Project calls are open for participation from anyone. If you are not able to attend a call, you can always browse to the Meeting Minutes for an update on the current discussion topics and decisions.

So, how do I get started with contributing to Jakarta EE?

The first thing you need to do is to create an Eclipse Account. If you already have an account, you may skip this step. If you want to do more than just joining the discussions on the mailing lists or calls, you need to sign the Eclipse Contributor Agreement (ECA). If you already have done this, you may skip this step as well.

The entire process is summarized below.

Congratulations! You can now be a Contributor to any project at the Eclipse Foundation.

So, how do I actually contribute then?

The easiest way of contributing is to submit Pull Requests to the project you are interested in. All the Jakarta EE Specification projects are currently located under the Eclipse EE4J GitHub organization.

The more you contribute, the more likely you are to be elected as a committer to the project (i.e. if you want to). If you get elected as a committer to a specification project, you will be asked to sign the Individual Working Group Participation Agreement. (*)

Congratulations! You are now a member of the Jakarta EE Working Group.

(*) This step is not necessary if you work for a company that is already a member of the Jakarta EE Working Group.


by Ivar Grimstad at December 06, 2019 04:09 PM

Joyful Open Liberty Developer Experience with Liberty Maven Plugin

by rieckpil at November 30, 2019 08:59 AM

Short feedback cycles during development are essential for your productivity. If you practice TDD you’ll agree on this even more. In the past, I’ve used several IDE plugins to achieve this for developing Jakarta EE applications. All worked but it wasn’t joyful. Adam Bien’s Watch and Deploy was a light at the end of the tunnel for a simple & generic solution. Recently I stumbled over the Liberty Maven Plugin from the Open Liberty team. This is really a gamechanger for great development experience for Liberty profile servers.

TL;DR: You’ll achieve the following with this Maven plugin:

  • Hot-reloading of code/configuration/dependency changes
  • TDD joy for developing Jakarta EE and MicroProfile applications
  • Easily debug your deployed application
  • Start your Open Liberty server without manual effort

Integrate the Liberty Maven Plugin to your project

Integrating this Open Liberty Maven plugin to an existing project, is as simple, like the following:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.rieckpil.blog</groupId>
    <artifactId>open-maven-plugin-review</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <jakarta.jakartaee-api.version>8.0.0</jakarta.jakartaee-api.version>
        <microprofile.version>3.2</microprofile.version>
        <junit-jupiter.version>5.5.0</junit-jupiter.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>${jakarta.jakartaee-api.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.microprofile</groupId>
            <artifactId>microprofile</artifactId>
            <version>${microprofile.version}</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>${junit-jupiter.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>open-maven-plugin-review</finalName>
        <plugins>
            <plugin>
                <groupId>io.openliberty.tools</groupId>
                <artifactId>liberty-maven-plugin</artifactId>
                <version>3.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
        </plugins>
    </build>
</project>

Open Liberty server configuration

By default, the plugin makes use of your configuration within src/main/liberty. To now configure the server, we can place our server.xml within src/main/liberty/config:

<?xml version="1.0" encoding="UTF-8"?>
<server description="rieckpil">

    <featureManager>
        <feature>cdi-2.0</feature>
        <feature>jpa-2.2</feature>
        <feature>jaxrs-2.1</feature>
        <feature>mpConfig-1.3</feature>
        <feature>mpHealth-2.0</feature>
        <feature>mpRestClient-1.3</feature>
    </featureManager>

    <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443"/>

    <!-- ${databaseName} is configured in the pom.xml -->
    <dataSource id="DefaultDataSource" jndiName="jdbc/h2">
        <jdbcDriver libraryRef="h2-library"/>
        <properties URL="jdbc:h2:mem:${databaseName}"/>
    </dataSource>

    <library id="h2-library">
        <file name="${server.config.dir}/h2.jar"/>
    </library>
</server>

If you, later on, start the Open Liberty server, you’ll find this file within target/liberty/wlp/usr/servers/defaultServer. To provide further resources e.g. a JDBC driver like in the example above, just place them next inside the same directory like your server.xml. You can also create new folder structures to separate the files from each other.

Similar to this, you can configure server parameters like environment, JVM or Liberty specific variables with this plugin. Since plugin version 3.1, you can achieve this within the properties section of your pom.xml:

<properties>
   <maven.compiler.source>11</maven.compiler.source>
   <maven.compiler.target>11</maven.compiler.target>
   <failOnMissingWebXml>false</failOnMissingWebXml>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
   <jakarta.jakartaee-api.version>8.0.0</jakarta.jakartaee-api.version>
   <microprofile.version>3.2</microprofile.version>
   <junit-jupiter.version>5.5.0</junit-jupiter.version>
   <!-- Configuration for Open Liberty -->
   <liberty.jvm.minHeap>-Xms512m</liberty.jvm.minHeap>
   <liberty.env.MY_MESSAGE>Hello World from Maven pom.xml!</liberty.env.MY_MESSAGE>
   <liberty.var.databaseName>jakarta</liberty.var.databaseName>
</properties>

The liberty.env can be then used for example by MicroProfile Config. The liberty.var variables are available within your server.xml for further configuration like it did with the name of the H2 database.

Find a list of all possible server configurations here.

Open Liberty in development mode = joy

Now comes the joyful part…

With this plugin you can launch the Open Liberty server on your machine in development mode:

mvn liberty:dev

If you execute this for the first time, the plugin will download the openliberty-kernel and all the required features you need. These files are stored within your local Maven repository folder (usually ~/.m2/repository) and can be therefore used for multiple projects.

Once all artifacts are downloaded, your Open Liberty server starts in development mode. If you now change the source code of your application, the plugin compiles and deploys your changes to the running server in a matter of seconds.

This is not limited to changes to your code. You can also add new dependencies to your Maven project or adjust your server configuration. Even if you add new features to your server.xml, they will be installed automatically.

Furthermore, you can run your (unit & integration) tests on-demand with hitting enter. In addition to this,  if you start the development mode with -DhotTests, your tests are executed on each change:

mvn liberty:dev -DhotTests

This is a gamechanger for the TDD (Test Driven Development) experience with Open Liberty.

Once Open Liberty is running in this development mode, you can also debug your application. The default port is 7777 and you can easily attach your IDE to the running JVM and debug your application.

To exit the development mode, either enter q in your terminal and hit enter or exit with CTRL+C.

Other Maven plugin goals

Besides this development mode, you can also start and stop your Open Liberty server with this project. The Maven goals for this are mvn liberty:start and mvn liberty:stop. The server content is located at target/liberty. There is no need to manually download Open Liberty anymore, as this plugin will do this.

If you want to start Open Liberty in the foreground, replace the start goal with run.

There are more useful goals for this Maven plugins to explore e.g dump, debug, create. The full list of goals is available on GitHub.

Summary of the Open Liberty Maven Plugin

With this Maven plugin, your Jakarta EE or MicroProfile development experience will takeoff. Given this plugin, there is no need to download the latest server anymore. The conventions for the server configuration makes it also more convenient to use compared to achieving the same with Docker.  This plugin will definitely be part of all my further Open Liberty projects and I can’t imagine developing applications without it anymore.

For a hands-on example, I’ve recorded a YouTube video:

Clone the example application for this review from GitHub or quickly add the plugin to your own project to see how joyful it makes developing with Open Liberty. There is also a recording available at the Open Liberty blog.

If you are looking for a solution to achieve hot reloading for other application servers, have a look at Adam Bien’s WAD.

Have fun using the Open Liberty Maven Plugin,

Phil

The post Joyful Open Liberty Developer Experience with Liberty Maven Plugin appeared first on rieckpil.


by rieckpil at November 30, 2019 08:59 AM

Jakarta EE integration tests with MicroShed Testing

by rieckpil at November 22, 2019 06:57 AM

Integration tests for your Jakarta EE application are essential. Testing the application in a full setup will ensure all of your components can work together. The Testcontainers project provides a great approach to use Docker containers for such tests. With MicroShed Testing you get a convenient way to use Testcontainers for writing integration tests for your Jakarta EE application. This is also true for Java EE or standalone MicroProfile applications.

Learn how to use this framework with this blog post. I’m using a Jakarta EE 8, MicroProfile 3.0, Java 11 application running on Open Liberty for the example.

Project setup for MicroShed Testing

For creating this project I’m using the following Maven Archetype:

mvn archetype:generate \     
  -DarchetypeGroupId=de.rieckpil.archetypes \
  -DarchetypeArtifactId=jakartaee8 \
  -DarchetypeVersion=1.0.0 \
  -DgroupId=de.rieckpil.blog \
  -DartifactId=review-microshed-testing \
  -DinteractiveMode=false

Besides the basic dependencies for Jakarta EE and Eclipse MicroProfile, we need some test dependencies also. As MicroShed Testing is using Testcontainers under the hood, we can add the official Testcontainers dependencies for starting a PostgreSQL and MockServer container.

Furthermore, we need JUnit 5 and the MicroShed Testing Open Liberty dependency itself. The Log4 1.2 SLF4J binding dependency is optional but improves the logging output of our tests.

As a result, the full pom.xml looks like the following:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.rieckpil.blog</groupId>
    <artifactId>review-microshed-testing</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <jakarta.jakartaee-api.version>8.0.0</jakarta.jakartaee-api.version>
        <microprofile.version>3.0</microprofile.version>
        <mockito-core.version>3.1.0</mockito-core.version>
        <junit-jupiter.version>5.5.0</junit-jupiter.version>
        <microshed-testing.version>0.6.1.1</microshed-testing.version>
        <testcontainers.version>1.12.4</testcontainers.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>${jakarta.jakartaee-api.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.microprofile</groupId>
            <artifactId>microprofile</artifactId>
            <version>${microprofile.version}</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.microshed</groupId>
            <artifactId>microshed-testing-liberty</artifactId>
            <version>${microshed-testing.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>${junit-jupiter.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.29</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>postgresql</artifactId>
            <version>${testcontainers.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>mockserver</artifactId>
            <version>${testcontainers.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mock-server</groupId>
            <artifactId>mockserver-client-java</artifactId>
            <version>5.5.4</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>review-microshed-testing</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
            </plugin>
            <plugin>
                <groupId>io.openliberty.tools</groupId>
                <artifactId>liberty-maven-plugin</artifactId>
                <version>3.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
            <!-- Plugin to run integration tests -->
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>3.0.0-M3</version>
                <executions>
                    <execution>
                        <id>integration-test</id>
                        <goals>
                            <goal>integration-test</goal>
                        </goals>
                        <configuration>
                            <trimStackTrace>false</trimStackTrace>
                        </configuration>
                    </execution>
                    <execution>
                        <id>verify</id>
                        <goals>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

With MicroShed Testing, you can either provide your own Dockerfile or in case of Open Liberty use the extension to have almost zero setup tasks. MicroShed Testing searches for a Dockerfile in either the root folder of your project or within src/main/docker.

For this application, I’m using the official Open Liberty extension from MicroShed Testing and therefore just have to configure the Open Liberty server within src/main/liberty. This folder contains a custom server.xml and the JDBC driver:

<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

    <featureManager>
        <feature>cdi-2.0</feature>
        <feature>jpa-2.2</feature>
        <feature>jaxrs-2.1</feature>
        <feature>mpConfig-1.3</feature>
        <feature>mpHealth-2.0</feature>
        <feature>mpRestClient-1.3</feature>
    </featureManager>

    <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443"/>
    
    <dataSource id="DefaultDataSource">
        <jdbcDriver libraryRef="postgresql-library"/>
        <properties.postgresql serverName="${POSTGRES_HOSTNAME}"
                               portNumber="${POSTGRES_PORT}"
                               databaseName="users"
                               user="${POSTGRES_USERNAME}"
                               password="${POSTGRES_PASSWORD}"/>
    </dataSource>

    <library id="postgresql-library">
        <fileset dir="${server.config.dir}/postgres"/>
    </library>
</server>

Jakarta EE application walkthrough

As I don’t want to provide a simple Hello World application for this example, I’m using an application with JPA & PostgreSQL and an external REST API as a dependency. This should mirror 80% of the basic applications out there.

The application contains two JAX-RS resources: SampleResource and PersonResource

First, you can retrieve a MicroProfile Config property from the SampleResource and a quote of the day. This quote of the day is fetched from a public REST API using MicroProfile RestClient:

@RegisterRestClient(baseUri = "https://quotes.rest")
public interface QuoteRestClient {

    @GET
    @Path("/qod")
    @Consumes(MediaType.APPLICATION_JSON)
    JsonObject getQuoteOfTheDay();
}

Using this public REST API, I’ll later demonstrate how to mock this call in your Jakarta EE integration test. The full resource looks like this:

@Path("sample")
@Produces(MediaType.TEXT_PLAIN)
public class SampleResource {

    @Inject
    @ConfigProperty(name = "message")
    private String message;

    @Inject
    @RestClient
    private QuoteRestClient quoteRestClient;

    @GET
    @Path("/message")
    public Response getMessage() {
        return Response.ok(message).build();
    }

    @GET
    @Path("/quotes")
    public Response getQuotes() {
        var quoteOfTheDayPointer = Json.createPointer("/contents/quotes/0/quote");
        var quoteOfTheDay = quoteOfTheDayPointer.getValue(quoteRestClient.getQuoteOfTheDay()).toString();
        return Response.ok(quoteOfTheDay).build();
    }
}

Second, the PersonResource allows clients to create and read person resources. We’ll store the persons in the PostgreSQL database using JPA:

@Path("/persons")
@ApplicationScoped
@Transactional(TxType.REQUIRED)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class PersonResource {

    @PersistenceContext
    private EntityManager entityManager;

    @GET
    public List<Person> getAllPersons() {
        return entityManager.createQuery("SELECT p FROM Person p", Person.class).getResultList();
    }

    @GET
    @Path("/{id}")
    public Person getPersonById(@PathParam("id") Long id) {
        var personById = entityManager.find(Person.class, id);

        if (personById == null) {
            throw new NotFoundException();
        }

        return personById;
    }

    @POST
    public Response createNewPerson(@Context UriInfo uriInfo, @RequestBody Person personToStore) {
        entityManager.persist(personToStore);

        var headerLocation = uriInfo.getAbsolutePathBuilder()
                .path(personToStore.getId().toString())
                .build();

        return Response.created(headerLocation).build();
    }
}

Integration test setup with MicroShed Testing

Next, we can set up the integration tests for our Jakarta EE (or Java EE or standalone MicroProfile) application. With MicroShed Testing, we can create a SharedContainerConfiguration to share the Docker containers between integration tests. As our system requires a running application, a PostgreSQL database, and a remote system, I’m creating three containers:

public class SampleApplicationConfig implements SharedContainerConfiguration {

    @Container
    public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>()
            .withNetworkAliases("mypostgres")
            .withExposedPorts(5432)
            .withUsername("duke")
            .withPassword("duke42")
            .withDatabaseName("users");

    @Container
    public static MockServerContainer mockServer = new MockServerContainer()
            .withNetworkAliases("mockserver");

    @Container
    public static ApplicationContainer app = new ApplicationContainer()
            .withEnv("POSTGRES_HOSTNAME", "mypostgres")
            .withEnv("POSTGRES_PORT", "5432")
            .withEnv("POSTGRES_USERNAME", "duke")
            .withEnv("POSTGRES_PASSWORD", "duke42")
            .withEnv("message", "Hello World from MicroShed Testing")
            .withAppContextRoot("/")
            .withReadinessPath("/health/ready")
            .withMpRestClient(QuoteRestClient.class, "http://mockserver:" + MockServerContainer.PORT);

}

The PostgreSQLContainer and MockServerContainer are part of a Testcontainer dependency. ApplicationContainer is now the first MicroShed Testing class we make use of.  You can use this wrapper for plain Jakarta EE or Java EE applications.

We can set up the ApplicationContainer with any environment variables, we want and provide MicroProfile Config properties in this way.  Next, you can define the readiness path of your application. For this, we can make use of MicroProfile Health and specify the readiness path /health/ready.

Furthermore, MicroShed Testing is capable to override the base URL for our MicroProfile RestClient. This allows us to use the MockServer for our integration tests.

Using the network alias our application is able to communicate with the MockServer and the PostgreSQL database within the Docker network.

Writing integration tests for Jakarta EE applications

Given this setup, we can finally start writing integration tests for our Jakarta EE application. MicroShed Testing can be enabled for a JUnit 5 test using @MicroShedTest. With @SharedContainerConfig you can reference the common system setup.

To test the SampleResource class, I’m expecting to get MicroProfile Config  property configured in the SharedContainerConfiguration. Furthermore, the quotes endpoint should return the quote of the day properly:

@MicroShedTest
@SharedContainerConfig(SampleApplicationConfig.class)
public class SampleResourceIT {
    
    @RESTClient
    public static SampleResource sampleEndpoint;
    
    @Test
    public void shouldReturnSampleMessage() {
        assertEquals("Hello World from MicroShed Testing",  
                sampleEndpoint.getMessage());
    }
    
    @Test
    public void shouldReturnQuoteOfTheDay() {

        var resultQuote = Json.createObjectBuilder()
                .add("contents",
                        Json.createObjectBuilder().add("quotes",
                                Json.createArrayBuilder().add(Json.createObjectBuilder()
                                        .add("quote", "Do not worry if you have built your castles in the air. " +
                                                "They are where they should be. Now put the foundations under them."))))
                .build();

        new MockServerClient(mockServer.getContainerIpAddress(), mockServer.getServerPort())
                .when(request("/qod"))
                .respond(response().withBody(resultQuote.toString(), com.google.common.net.MediaType.JSON_UTF_8));

        var result = sampleEndpoint.getQuotes();

        System.out.println("Quote of the day: " + result);

        assertNotNull(result);
        assertFalse(result.isEmpty());
    }
}

Injecting the JAX-RS resource with @RESTClient within the integration test allows us to make the HTTP call like using a JAX-RS client.

The integration test for PersonResource is more advanced. I’m testing the flow of creating a new person and then querying for it:

@MicroShedTest
@SharedContainerConfig(SampleApplicationConfig.class)
public class PersonResourceIT {
    
    @RESTClient
    public static PersonResource personsEndpoint;
    
    @Test
    public void shouldCreatePerson() {
        Person duke = new Person();
        duke.setFirstName("duke");
        duke.setLastName("jakarta");
        
        Response result = personsEndpoint.createNewPerson(null, duke);

        assertEquals(Response.Status.CREATED.getStatusCode(), result.getStatus());
        var createdUrl = result.getHeaderString("Location");
        assertNotNull(createdUrl);

        var id = Long.valueOf(createdUrl.substring(createdUrl.lastIndexOf('/') + 1));
        assertTrue(id > 0, "Generated ID should be greater than 0 but was: " + id);
        
        var newPerson = personsEndpoint.getPersonById(id);
        assertNotNull(newPerson);
        assertEquals("duke", newPerson.getFirstName());
        assertEquals("jakarta", newPerson.getLastName());
    }
}

Summary of MicroShed Testing for Jakarta EE integration tests

Even though the project is in its early stages, it provides excellent support for writing Jakarta EE integrations tests using Testcontainers. There are also dedicated dependencies available for Open Liberty and Payara. With them, it’s, even more, simpler to use. You should give it a try and provide feedback to further evolve it.

There are also good examples available for different application setups.

For more information follow this guide on Open Liberty. Furthermore, visit the GitHub repository or the official project homepage. You can find this application also on GitHub.

Have fun writing Jakarta EE integration tests with MicroShed Testing,

Phil

The post Jakarta EE integration tests with MicroShed Testing appeared first on rieckpil.


by rieckpil at November 22, 2019 06:57 AM

Coming Soon: Payara Platform Monitoring Console

by Jan Bernitt at November 21, 2019 12:09 PM

We are happy to announce that from the Payara Platform 5.194 release onwards Payara Server ships with a built-in monitoring console that allows a visual peek under the hood of the server.


by Jan Bernitt at November 21, 2019 12:09 PM

Modernizing our GitHub Sync Toolset

November 19, 2019 08:10 PM

I am happy to announce that my team is ready to deploy a new version of our GitHub Sync Toolset on November 26, 2019 from 10:00 to 11:00 am EST.

We are not expecting any disruption of service but it’s possible that some committers may lose write access to their Eclipse project GitHub repositories during this 1 hour maintenance window.

This toolset is responsible for syncronizing Eclipse committers accross all our GitHub repositories and on top of that, this new release will start syncronizing contributors.

In this context, a contributor is a GitHub user with read access to the project GitHub repositories. This new feature will allow committers to assign issues to contributors who currently don’t have write access to the repository. This feature was requested in 2015 via Bug 483563 - Allow assignment of GitHub issues to contributors.

Eclipse Committers are reponsible for maintaining a list of GitHub contributors from their project page on the Eclipse Project Management Infrastructure (PMI).

To become an Eclipse contributor on a GitHub for a project, please make sure to tell us your GitHub Username in your Eclipse account.


November 19, 2019 08:10 PM

Jakarta EE Community Update November 2019

by Tanja Obradovic at November 19, 2019 06:52 PM

Now that Jakarta EE 8 has been available for a couple of months, I want to share news about some of the great committee work that’s been happening. I also want to tell you about our latest Jakarta EE-compatible product, and make sure you have links to the recordings of our Jakarta EE community calls and presentations.

 Due to the timing of this update, I’ve included news about activities in the first half of November as well as October.

 

Another Jakarta EE-Compatible Product

I’m very pleased to tell you that Payara Server is now fully certified as a Jakarta EE 8-compatible implementation. If you’re not familiar with Payara Server, take a few minutes to learn more about this innovative, cloud native application server.

 The Payara team told us they found the compatibility process smooth and easy. To learn more about the benefits of being certified as a Jakarta EE-compatible product and the process to get listed, click here.

 

Jakarta EE 8 Feedback Will Drive Improvements

The Jakarta EE Steering Committee started a community retrospective on the Jakarta EE 8 release, sharing this document to drive the process.

You’ll also see retrospectives from each of the other Jakarta EE Working Group committees as they look to gather community input on improvements for the next release. Once all of the input is collected, we’ll summarize and publish the findings.

 

Jakarta EE 9 Delivery Plan to Be Ready December 9

Jakarta EE 9 planning is underway, and the Steering Committee has published a resolution requesting Jakarta EE Platform Project leaders to deliver a Jakarta EE 9 Delivery Plan, including a release date, to the Steering Committee no later than December 9, 2019.

 According to the resolution, the Jakarta EE 9 Delivery Plan should:

  • Implement the “big bang”
  • Include an explicit means to identify and enable specifications that are unnecessary or unwanted to be deprecated or removed 
  • Move all remaining specification APIs to the Jakarta namespace
  • Add no new specifications, apart from those pruned from Java SE 8 where appropriate, unless those specifications will not impact the target delivery date

The resolution is now with the Jakarta EE Platform Project team, which is actively looking into the Steering Committee requests. The Platform Project team will put a higher priority on meeting the Steering Committee resolution requests as soon as possible rather than adding more functionality to the release.

 You can read the minutes of the Jakarta EE Platform Project team meetings here.

 

New Chair for the Jakarta EE Specification Committee

We welcome Paul Buck as the non-voting Chair of the Jakarta EE Specification Committee. Paul is Vice President of Community Development at the Eclipse Foundation, and was unanimously elected to his new role.

 

Jakarta EE 8 Restructuring Continues

In the push to complete Jakarta EE 8, a number of planned improvements were deferred. Here’s a brief summary of the improvements the Jakarta EE Specification Committee is currently discussing:

  • Updating project ids and technical namespaces. For example:
    • ee4j.jms becomes ee4j.messaging
    • https://github.com/eclipse-ee4j/jms-api becomes https://github.com/eclipse-ee4j/messaging-api
    • javax.jms becomes jakarta.messaging
  • Updating project names. For example:
    • Jakarta Server Faces becomes Jakarta Faces
  • Whether top-level projects should be changed to include both specifications and compatible implementations as subpages
  • How to address the decision to rename TCK files from “eclipse-” to “jakarta-”

 

Time to Jakartify More Specifications

When Jakarta EE 8 was released, we provided specifications for the Jakarta EE Full Profile and Jakarta EE Web Profile. Now that we’ve acquired the copyright for additional specifications, it’s time for the community to Jakartify them so they can be contributed to Jakarta EE.

 

To help you get started:

And, here’s the list of specifications that are ready for the community to "Jakartify":

•    Jakarta Annotations

•    Jakarta Enterprise Beans

•    Jakarta Expression Language

•    Jakarta Security

•    Jakarta Server Faces

•    Jakarta Interceptors

•    Jakarta Authorization

•    Jakarta Activation

•    Jakarta Managed Beans

 

•    Jakarta Deployment

•    Jakarta XML RPC

•    Jakarta Authentication

•    Jakarta Mail

•    Jakarta XML Binding

•    Jakarta RESTful Web Services

•    Jakarta Web Services Metadata

•    Jakarta XML Web Services

•    Jakarta Connectors

 

•    Jakarta Persistence

•    Jakarta JSON Binding

•    Jakarta JSON Processing

•    Jakarta Debugging Support for Other Languages

•    Jakarta Server Pages

•    Jakarta Transactions

•    Jakarta WebSocket

 

 

On a related note, the Specification Committee is also working to further define compatibility testing requirements for the full platform and web profile specifications for subsequent releases of Jakarta EE-compatible products.

 

Jakarta EE Marketing Plan Nearly Finalized

We expect the Jakarta EE 2020 marketing plan and budget to be approved by the end of November.

The Marketing Committee is also looking to choose a Committee Chair very soon. In the meantime, the Eclipse Foundation will be actively participating in KubeCon, NA. If you’re there, be sure to drop by booth S5 to talk to our technical experts and check out the demos on the cloud native Java projects.

 

Join Community Update Calls

Every month, the Jakarta EE community holds a Community Call for everyone in the Jakarta EE community. For upcoming dates and connection details, see the Jakarta EE Community Calendar.

 We know it’s not always possible to join calls in real time, so here are links to the recordings and presentations:

 

A Look Back at October Events

October was another busy month for Jakarta EE and cloud native Java events as we participated in. Beside EclipseCon Europe 2019, we were present at Trondheim Developer Conference in Norway, Open Source Summit EU in France, SpringOne Platform, Think London - UK and Joker<?> - Russia.

In addition to many reports and blogs you may find on the participation, I would like to point out the ECE 2019 Community Day collaboration between IoT and Cloud Native Java teams. Even though it was just a starting point attempt to work on the solution by both teams, it was great seeing two Eclipse Foundation communities working together! I am looking for more of these collaborations in the future. Please look for blog from Jens Reimann (@ctron) from Red Hat on this. 

 

Stay Connected With the Jakarta EE Community

The Jakarta EE community is very active and there are a number of channels to help you stay up to date with all of the latest and greatest news and information. Tanja Obradovic’s blog summarizes the community engagement plan, which includes:

•      Social media: Twitter, Facebook, LinkedIn Group

•      Mailing lists: jakarta.ee-community@eclipse.org and jakarta.ee-wg@eclipse.org

•      Newsletters, blogs, and emails: Eclipse newsletter, Jakarta EE blogs, monthly update emails to jakarta.ee-community@eclipse.org, and community blogs on “how are you involved with Jakarta EE”

•      Meetings: Jakarta Tech Talks, Jakarta EE Update, Jakarta Town Hall, and Eclipse Foundation events and conferences

 

Subscribe to your preferred channels today. And, get involved in the Jakarta EE Working Group to help shape the future of open source, cloud native Java.

 

To learn more about Jakarta EE-related plans and check the date for the next Jakarta Tech Talk, be sure to bookmark the Jakarta EE Community Calendar.


by Tanja Obradovic at November 19, 2019 06:52 PM

Java projelerinde sürdürülebilir kalite meetup’ı ardından

by Hüseyin Akdogan at November 18, 2019 06:00 AM

13.11.2019 Çarşamba günü sevgili Altuğ hocam ve Gökalp Gürbüzer ile Kod Gemisi’nden Destan Sarpkaya’yı “Java Projelerinde Sürdürülebilir Kalite” meetup’ında ağırladık. Özelde Java, genelde yazılım projelerinde sürdürülebilir kalite pek çok boyutu olan bir konu. Biz meseleye yazılım mimarisi, yazılım mimarlarının rolü noktasından giriş yaptık.

Destan bey öncelikle net tanımlama yapmanın zorluğundan bahsedip özet ve subjektif bir tanımlamayla, “bir yazılımın bileşenlerinin nasıl oluşturulacağı ve birbirleriyle nasıl etkileşeceğine dair verilen kararlar”ın yazılımın mimarisini oluşturduğunu, bu kararları verenlerin de yazılım mimarları olduğunu belirtip, Martin Fowler’ın konuya sosyal boyutu da ilave ederek çizdiği daha geniş bir çerçeveden söz etti. 

Konuşma devamla “kalite nedir?” sorusuna cevap bulma aşamasına geldi. Destan beye göre kodu kaliteli kılan en önemli şey kodun kolay değiştirebilir olmasıdır. Kaliteyi belirlemenin geniş bir çerçeve gerektirdiğini ifade eden Destay bey “kod iş görüyor mu, müşterinin isteğini yerine getiriyor mu, peki performanslı mı, güvenli mi, okunaklı mı, maintain edilebiliyor mu, best practice’lere, defacto standartlara uygun mu?” gibi cevabı aranması gereken bir dizi soru bulunduğunu, işin bu noktada da bitmediğini, ölçeklenebilirlik, yeniden kullanılabilirlik, başka ortamlarda çalıştırılabilirlik, konfigüre edilebilirlik gibi diğer pek çok boyut ve kriter bulunduğunu ifade etti.

Bu noktada, kalite ölçümü için standartların ne olduğu veya olması gerektiğini konuşmaya başladık. Destan bey, örneğin “neye göre okunabilir, ölçeklenebilir?” gibi soruların sorulması gerektiğini ve bu noktada belirleyici olanın domain olduğunu ifade edip her proje için kalite standart ve ölçütlerinin belirlenmesi gerektiğininin altını çizdi. Destan bey devamla, mimariyi belirlemek kadar, sürdürülebilirliğini sağlamanın önemli olduğunu ve sürdürülebilirlik için kendi tabiriyle 3 cephede savaş vermek durumunda olduğumuzu belirtti. Bu üç cephe

  • Teknik cephe
  • Sosyal cephe
  • Politik cephe

Teknik cephenin belki işin en kolay kısmı olduğunu, asıl zorluğun diğer 2 cephede yaşandığını belirten Destan beye göre, örneğin araştırma sorgulama yapmadan, cargo cult effect ile iş yapan bir yazılımcıyla ilişkili iyileştirme süreçleri sosyal cephenin konusudur çünkü bu problemin teknik bir çözümü yoktur.

Destan bey devamla yazılım ekiplerinde bir kültür oturtmanın gerekliliği ve bunun zorluğu üzerinde durdu, bu noktada kültür ile motivasyon ilişkisinin önemini vurguladı. Sosyal cephede verilecek mücadelenin en önemli amacının motivasyon yükseltmek olduğunu ifade edip, iş doyumu ve kişiliğin motivasyon noktasında belirleyici en temel iki faktör olduğunun altını çizdi.

Politik cephe ile ilgili olarak Destan bey “bir projenin hem başarısını hem kalitesini hem mimari kararlarını etkileyen politik kriterlerdir” diyor. Politik boyutta ilk düşünülmesi gereken şeyin projenin maliyeti olduğunu, maliyetin zaman anlamına geldiğini ifade ediyor. Zaman kalite ilişkisi için “size ayırlan zaman proje kalitesi ve mimari kararlarınızı doğrudan etkiler” diyen Destan bey, genel olarak geliştiricler, proje mimarlarının zaman hakkında çok söz hakkına sahip olmadığını, kaliteli yazılım geliştirmenin maliyetli bir iş olduğunu ve karar vericileri buna ikna etme zorunluluğu bulunduğunun altını çizdi.

Tüm çabalara rağmen yeterli zaman alınamadığı durumlarda, bu olumsuzluğun etkilerini tahmin edilebilir ve yönetilebilir kılmak için belgelemenin önemini vurgulayan Destan bey, workaround veya dirty hack yapılan durumlarda kod içi dokümantasyonun, kodun nasıl refactor edileceğinin belgelenmesinin, uzun vadede kaliteyi artırıcı çok önemli bir unsur olduğunu ancak bu önemi bazen geliştiricilere anlatma ve kabul ettirmede zorluklar yaşandığını ifade etti. Bu noktada bir kalite sponsoruna sahip olmanın avantajını vurgulayan Destan bey, kurumsal yapı içinde geliştiricinin arkasında duracak bir yöneticiye ihtiyacının altını çizdi.

En başta ifade ettiğim gibi sürdürülebilir kalite pek çok boyutu olan bir konu ve yaklaşık 1 saat boyunca burada ifade edip, özetleyemediğim daha pek çok önemli noktaya temas edildi. Bizim için oldukça keyifli ve öğretici geçen bu sohbet için Destan beye tekrar teşekkür ediyoruz. Unutmadan, diğer online meetup’larımız gibi bu meetup’ı da iTunes ve Spotify üzerinden JUG İstanbul podcast kanalından takip edebileceğinizi hatırlatmak istiyorum.

Bir başka etkinlikte görüşmek üzere…


by Hüseyin Akdogan at November 18, 2019 06:00 AM

Hello Quarkus Supersonic Subatomic Java World

by Hayri Cicek at November 17, 2019 09:37 AM

Quarkus is the new Supersonic Subatomic Java framework tailored for GraalVM and HotSpot.
In this quick tutorial, I will show you how to get started with Quarkus.

by Hayri Cicek at November 17, 2019 09:37 AM

Create real-time applications with Jakarta EE WebSocket

by rieckpil at November 14, 2019 05:52 AM

If your application has real-time requirements like within a chat, the WebSocket technology might be a good fit. With WebSockets, you can create two-way communication channels between a server and a client. The JSR 356 specification defines a standard way of creating and managing WebSocket clients and servers for Java. It’s also part of Jakarta EE as Jakarta EE WebSocket with the current version 1.1. Learn how to use the Jakarta EE WebSocket specification within this blog post while writing a small stock exchange application.

Jakarta EE 8 project setup

To create the sample application I make use of one of my Maven Archetypes. The Maven project uses Java 11 and the Jakarta EE platform dependency with version 8.0.0:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.rieckpil.blog</groupId>
    <artifactId>websockets-with-jakarta-ee</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <jakarta.jakartaee-api.version>8.0.0</jakarta.jakartaee-api.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>${jakarta.jakartaee-api.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>websockets-with-jakarta-ee</finalName>
        <!-- further plugins -->
    </build>
</project>

Next, I’m using Open Liberty for the runtime. The server.xml to configure Open Liberty is straightforward:

<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

    <featureManager>
        <feature>javaee-8.0</feature>
    </featureManager>

    <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443"/>

    <quickStartSecurity userName="duke" userPassword="dukeduke"/>
</server>

As we are using our own server configuration, the open-liberty:kernel-java11 Docker image fits perfect for the base image:

FROM open-liberty:kernel-java11
COPY --chown=1001:0  target/websockets-with-jakarta-ee.war /config/dropins/
COPY --chown=1001:0  server.xml /config

Creating a WebSocket endpoint

We have two options to create WebSocket endpoints. First, we can create them programmatically while extending the javax.websocket.Endpoint class. Second, we can use the @ServerEndpoint annotation.

For this example, I’m using the approach with annotations. This allows us to use further annotations like @OnOpen, @OnMessage, etc. on methods of our endpoint class. With these we can define how to handle the different lifecycle phases of establishing a connection, sending a message, and closing the connection:

@ServerEndpoint(value = "/stocks")
public class StockExchangeEndpoint {

    private static Set<Session> sessions = new HashSet<>();

    public static void broadcastMessage(String message) {
        for (Session session : sessions) {
            try {
                session.getBasicRemote().sendObject(message);
            } catch (IOException | EncodeException e) {
                e.printStackTrace();
            }
        }
    }

    @OnOpen
    public void onOpen(Session session) {
        System.out.println("WebSocket opened: " + session.getId());
        sessions.add(session);
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("Stock information received: " + message + " from " + session.getId());
        try {
            session.getBasicRemote().sendObject(message);
        } catch (IOException | EncodeException e) {
            e.printStackTrace();
        }
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        System.out.println("WebSocket error for " + session.getId() + " " + throwable.getMessage());
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        System.out.println("WebSocket closed for " + session.getId() 
                            + " with reason " + closeReason.getCloseCode());
        sessions.remove(session);
    }
}

In the example above, I’ve added a method for each of these lifecycle phases. As we want to broadcast messages to all of our subscribers, later on, we can store all active sessions in a Set. Once a message arrives at our WebSocket endpoint, I’m replying with the same message to the sender using session.getBasicRemote().sendObject(message).

With this setup, our WebSocket endpoint is now available at ws://localhost:9080/stocks and waiting for clients to connect.

Adding support to encode and decode JSON with Jakarta EE

The specification defines only two default data formats for WebSocket messages: Text and Binary.  Fortunately,  Jakarta EE WebSocket allows us to add custom decoders and encoders for our messages. To demonstrate this, I’ll create a decoder and encoder for JSON based messages.

Creating a custom encoder is done by implementing either Encoder.Text<T> or Encoder.Binary<T> (or their streaming equivalents). A naive text-based JSON encoder might look like the following:

public class JSONTextEncoder implements Encoder.Text<JsonObject> {

    @Override
    public String encode(JsonObject object) throws EncodeException {
        return object.toString();
    }

    @Override
    public void init(EndpointConfig config) {
    }

    @Override
    public void destroy() {
    }
}

Writing a custom decoder works similarly. You just have to implement one additional method willDecode(String s) to determine whether or not your decoder is able to decode an incoming message. To determine this, I’m trying to parse the incoming message to a JSON object (there might be better solutions):

public class JSONTextDecoder implements Decoder.Text<JsonObject> {

    @Override
    public JsonObject decode(String s) throws DecodeException {
        try (JsonReader jsonReader = Json.createReader(new StringReader(s))) {
            return jsonReader.readObject();
        }
    }

    @Override
    public boolean willDecode(String s) {
        try (JsonReader jsonReader = Json.createReader(new StringReader(s))) {
            jsonReader.readObject();
            return true;
        } catch (JsonException e) {
            return false;
        }
    }

    @Override
    public void init(EndpointConfig config) {
    }

    @Override
    public void destroy() {
    }
}

Once your custom decoder and encoder are ready to use, you have to configure them in your server endpoint like the following:

@ServerEndpoint(value = "/stocks", 
   decoders = {JSONTextDecoder.class}, 
   encoders = {JSONTextEncoder.class})
public class StockExchangeEndpoint {

    public static void broadcastMessage(JsonObject message) {
        for (Session session : sessions) {
            try {
                session.getBasicRemote().sendObject(message);
            } catch (IOException | EncodeException e) {
                e.printStackTrace();
            }
        }
    }

    @OnMessage
    public void onMessage(JsonObject message, Session session) {
        System.out.println("Stock information received: " + message + " from " + session.getId());
        try {
            session.getBasicRemote().sendObject(message);
        } catch (IOException | EncodeException e) {
            e.printStackTrace();
        }
    }

    // the rest stays the same
}

With this configuration, we can now accept JsonObject as a message type for our @OnMessage method and also send JsonObject data to our clients.

Connecting to the WebSocket endpoint using Jakarta EE

If you want to connect to a WebSocket endpoint from a different Jakarta EE application, you can create a class with @ClientEndpoint. Within this class you can now use the same lifecycle annotations that you’ve already seen in the server endpoint (@OnMessage, etc.):

@ClientEndpoint(decoders = {JSONTextDecoder.class}, encoders = {JSONTextEncoder.class})
public class StockExchangeClient {

    @OnMessage
    public void processMessageFromStockExchangeServer(JsonObject message) {
        System.out.println("Message came from the Stock Exchange server: " + message);
    }
}

Also, make sure to add your custom decoders and encoders.

Next, to connect the client to an actual endpoint, you can use the WebSocketContainer class and connect to a given URL:

public class StockExchangeNotifier {

    private Session session;

    @PostConstruct
    public void init() {
        WebSocketContainer container = ContainerProvider.getWebSocketContainer();
        try {
            this.session = container.connectToServer(StockExchangeClient.class,
                    new URI("ws://localhost:9080/stocks"));
        } catch (DeploymentException | IOException | URISyntaxException e) {
            e.printStackTrace();
        }
    }
}

In this example, as I’m printing each client connection and the incoming message to the client, the output looks like the following:

WebSocket opened: N9Im5dyQIbC_itLvFqmsWM-
Message came from the Stock Exchange server: {"stock":"DKE-42","price":167.91}
Message came from the Stock Exchange server: {"stock":"DKE-42","price":142.98}

Furthermore, I’m using an EJB timer to broadcast a new WebSocket message every five seconds:

@Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
public void sendNewStockExchangeInformation() {
    JsonObject stockInformation = Json.createObjectBuilder()
        .add("stock", "DKE-42")
        .add("price", new BigDecimal(ThreadLocalRandom.current()
                                       .nextDouble(250.00))
                                       .setScale(2, RoundingMode.DOWN))
        .build();

    StockExchangeEndpoint.broadcastMessage(stockInformation);
}

Connecting to the WebSocket endpoint with JavaScript

In addition, we can now connect to our WebSocket endpoint using JavaScript. The WebSocket standard API is part of every browser and can be used right out-of-the-box.

For a short demo, I’m creating a frontend to connect to the endpoint, send messages with a form and display all incoming messages like the following:

Jakarta EE WebSocket example application

Lastly, the JavaScript part to make this work is the following:

const webSocket = new WebSocket('ws://localhost:9080/stocks');

webSocket.onerror = function (event) {
    onError(event)
};
webSocket.onopen = function (event) {
    onOpen(event)
};
webSocket.onmessage = function (event) {
    onMessage(event)
};

function onMessage(event) {
    const eventPayload = JSON.parse(event.data);
    document.getElementById('stockInformation').innerHTML += 
      `<tr><td>${eventPayload.stock}</td><td>${eventPayload.price} $</td></tr>`;
}

function onOpen(event) {
    document.getElementById('connectionMessage').innerHTML = 'Connection established';
}

function onError(event) {
    alert('An error occurred:' + event.data);
}

function send() {
    const payload = {
        'stock': document.getElementById('stockName').value,
        'price': document.getElementById('stockPrice').value
    };

    webSocket.send(JSON.stringify(payload));
}

You can find the HTML markup for this example on GitHub.

Have fun writing applications with Jakarta EE WebSocket,

Phil

The post Create real-time applications with Jakarta EE WebSocket appeared first on rieckpil.


by rieckpil at November 14, 2019 05:52 AM

Understanding JMS(MDB) transaction scopes in JakartaEE application

November 13, 2019 10:00 PM

Most useful way to deal with JMS in JakartaEE application is MDB(Message Driven Beans). This type of bean acts as a JMS message listener to which messages can be delivered from either a queue or a topic.

Message Driven Bean supports only Required and NotSupported scopes as there is no incoming transaction context.

  • @Required: Transaction starts before read from queue (before onMessage). All next resource calls will use this transaction context. In case transaction rollback or some RuntimeException, - message will be roll back to destination. Container acknowledges delivery after TX commit;

  • @NotSupported: No transaction started. Application server acknowledges delivery on successful onMessage(). In case RuntimeException, - message will be returned to destination;

In both cases above, when message was returned to the destination, container will do redelivery according to application server configuration. For example on Wildfly it is: max-delivery-attempts and redelivery-delay.

/subsystem=messaging-activemq/server=default/address-setting=#:read-attribute(name=max-delivery-attempts)

Be careful with redelivery configuration as in case "poisen message" it can negative affect performance of your application or even server.

When you use container-managed transactions, you can invoke next MessageDrivenContext methods:

  • setRollbackOnly: marks the current transaction to rollback.
  • getRollbackOnly: check current transaction has been marked for rollback or not.

In case bean-managed transactions you need to manually control transaction by UserTransaction methods and you also can set the activation configuration property acknowledgeMode to Auto-acknowledge or Dups-ok-acknowledge to specify how the message received by the message-driven bean to be acknowledged.

Ok. Let's pay attention on typical use cases and potentially issues with default configurations. Often enough developers use MDB to do relatively long tasks that should be executed asynchronously. So typical message bean in this case will looks like:

@JMSDestinationDefinition(
        name = TxRequiredMessagerDrivenBean.TX_REQUIRED_QUEUE,
        interfaceName = "javax.jms.Queue"
)
@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = TxRequiredMessagerDrivenBean.TX_REQUIRED_QUEUE),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
//@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class TxRequiredMessagerDrivenBean implements MessageListener {

    public final static String TX_REQUIRED_QUEUE = "java:global/jms/txRequiredQueue";

    @Resource
    MessageDrivenContext messageDrivenContext;

    @Override
    public void onMessage(Message msg) {
        System.out.println("Got new message.");
        try {
            System.out.println("Hello TxRequiredMessagerDrivenBean!");
            for (int x = 1; x < 40; x++) {
                Thread.sleep(10_000l);
                System.out.println("Long transaction: " + (10 * x) + " sec.");
            }
        } catch (Exception ex) {
            System.err.println(ex);
            messageDrivenContext.setRollbackOnly();
        }
        System.out.println("Message  successfully processed");
    }
}

Now take a look to result of our bean invocation:

INFO  (Thread-1 (ActiveMQ-client-global-threads)) Got new message.
INFO  (Thread-1 (ActiveMQ-client-global-threads)) Hello TxRequiredMessagerDrivenBean!
INFO  (Thread-1 (ActiveMQ-client-global-threads)) Long transaction: 10 sec.
...
INFO  (Thread-1 (ActiveMQ-client-global-threads)) Long transaction: 290 sec.
...
WARN  [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012117: TransactionReaper::check timeout for TX 0:ffff7f000101:3b3ecbca:5dcc2894:13 in state  RUN
WARN  [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012095: Abort of action id 0:ffff7f000101:3b3ecbca:5dcc2894:13 invoked while multiple threads active within it.
WARN  [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012381: Action id 0:ffff7f000101:3b3ecbca:5dcc2894:13 completed with multiple threads - thread Thread-1 (ActiveMQ-client-global-threads) was in progress with java.lang.Thread.sleep(Native Method) org.kostenko.example.jms.transaction.TxRequiredMessagerDrivenBean.onMessage(TxRequiredMessagerDrivenBean.java:40)
...
WARN  [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012108: CheckedAction::check - atomic action 0:ffff7f000101:3b3ecbca:5dcc2894:13 aborting with 1 threads active!
...
WARN  [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012121: TransactionReaper::doCancellations worker Thread[Transaction Reaper Worker 0,5,main] successfully canceled TX 0:ffff7f000101:3b3ecbca:5dcc2894:13
...
INFO  (Thread-3 (ActiveMQ-client-global-threads)) Got new message.
INFO  (Thread-3 (ActiveMQ-client-global-threads)) Hello TxRequiredMessagerDrivenBean!
INFO  (Thread-1 (ActiveMQ-client-global-threads)) Long transaction: 300 sec.
INFO  (Thread-3 (ActiveMQ-client-global-threads)) Long transaction: 10 sec.
INFO  (Thread-1 (ActiveMQ-client-global-threads)) Long transaction: 310 sec.
INFO  (Thread-3 (ActiveMQ-client-global-threads)) Long transaction: 20 sec.
INFO  (Thread-1 (ActiveMQ-client-global-threads)) Long transaction: 320 sec.
...
INFO  (Thread-3 (ActiveMQ-client-global-threads)) [] Long transaction: 90 sec.
INFO  (Thread-1 (ActiveMQ-client-global-threads)) [] Long transaction: 390 sec.
INFO  (Thread-1 (ActiveMQ-client-global-threads)) [] Message  successfully processed
WARN  [com.arjuna.ats.arjuna] (Thread-1 (ActiveMQ-client-global-threads)) [] ARJUNA012077: Abort called on already aborted atomic action 0:ffff7f000101:3b3ecbca:5dcc2894:13
WARN  [org.apache.activemq.artemis.ra] (Thread-1 (ActiveMQ-client-global-threads)) [] AMQ152006: Unable to call after delivery: javax.resource.spi.LocalTransactionException: javax.transaction.RollbackException: ARJUNA016102: The transaction is not active! Uid is 0:ffff7f000101:3b3ecbca:5dcc2894:13
  Caused by: javax.transaction.RollbackException: ARJUNA016102: The transaction is not active! Uid is 0:ffff7f000101:3b3ecbca:5dcc2894:13
...
WARN  [org.apache.activemq.artemis.core.client] (Thread-1 (ActiveMQ-client-global-threads)) [] AMQ212009: resetting session after failure

From log above we can see that:

  • TransactionAttributeType.REQUIRED was used by default;
  • Started transaction was canceled by default timeout in 300 sec;
  • Container detected TX cancellation - did message redelivery and MDB starts new transaction;
  • Old thread continue work with first message processing, but the transaction already is not active;

So, keep this behavior in mind if you planning to play with long tasks and Message Driven Beans then depends on requirements few solutions is possible here:

  • Avoid long transaction usage. If long TX is not necessary - always use TransactionAttributeType.NOT_SUPPORTED
  • Increase default transaction timeout
  • Use an annotation @ActivationConfigProperty(propertyName="transactionTimeout", propertyValue="xxx") to specify custom transaction timeout for MDB like:
@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = TxRequiredMessagerDrivenBean.TX_REQUIRED_QUEUE),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    @ActivationConfigProperty(propertyName = "transactionTimeout", propertyValue="500")
})

Source code of test application available on GitHub


November 13, 2019 10:00 PM

Never use Java primitives for math calculation

November 07, 2019 10:00 PM

This is well known stuff about representation of Floating point types in java, but time from time each developer can forget about

@Test
public void primitiveTest() {

    // right way:
    BigDecimal bgDcml = BigDecimal.valueOf(100000f).multiply(BigDecimal.valueOf(750f)).multiply(BigDecimal.valueOf(15f)).setScale(0);
    BigDecimal bgDcml2 = BigDecimal.valueOf(0.04d).multiply(BigDecimal.valueOf(15.0d));

    // wrong way:
    float flt = 100000f * 750f * 15f;
    float flt2 = 0.04f * 15.0f;

    System.out.println("BigDecimal (correct): " + bgDcml);
    System.out.println(String.format("Float (incorrect): %s (%s)", flt, new BigDecimal(flt)));
    System.out.println("BigDecimal (correct): " + bgDcml2);
    System.out.println(String.format("Float (incorrect): %s", flt2));
}
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
BigDecimal (correct): 1125000000
Float (incorrect): 1.12499994E9 (1124999936)
BigDecimal (correct): 0.600
Float (incorrect): 0.59999996

November 07, 2019 10:00 PM

The Payara Monthly Catch for October 2019

by Jadon Ortlepp (Jadon.Ortlepp@Payara.fish) at November 07, 2019 12:22 PM

Apologies for the late edition this month! Your humble author has been on the road with recent conferences in Europe. But I hope I can make it up to you!

Below you will find a curated list of some of the most interesting news, articles and videos from this month. Cant wait until the end of the month? then visit our twitter page where we post all these articles as we find them! 


by Jadon Ortlepp (Jadon.Ortlepp@Payara.fish) at November 07, 2019 12:22 PM

Jakarta Batch garbage collection with Jberet

November 03, 2019 10:00 PM

To implement Jakarta Batch Specification Wildfly uses JBeret as implementation of JSR 352 (Batch Applications for the Java Platform). During processing, last one persists some working data to the memory, JDBC or another repository depends on configuration.

In case intensive usage it can collect lot of data and as result provoke some application server performance issues. To cleanup unwanted job data you can design your own solution or use provided by Jberet org.jberet.repository.PurgeBatchlet in standard way:

<job id="batchGarbageCollector" 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/jobXML_1_0.xsd"
     version="1.0">
    <step id="batchGarbageCollector.step1">
        <batchlet ref="org.jberet.repository.PurgeBatchlet">
            <properties>
                <property name="sqlFile" value="#{jobParameters['sqlFile']}"/>
            </properties>
        </batchlet>
    </step>
</job>

From the documentation PurgeBatchlet supports rich set of properties and looks pretty good, BUT on practice lot of them does not work as expected. I tried numberOfRecentJobExecutionsToKeep and batchStatuses on both WF repositories (inMemory and JDBC) and on both of them it does not work for me.

I am getting output like below, but garbage still was with me :(

...
INFO  [org.jberet] (Batch Thread - 8) [] JBERET000023: Removing javax.batch.runtime.JobExecution 35256804
INFO  [org.jberet] (Batch Thread - 8) [] JBERET000023: Removing javax.batch.runtime.JobExecution 35256806
...

Good news is, that in case using JDBC repository job parameter sqlFile works as expected and PurgeBatchlet executes provided SQL... without any log outputs.

Source code of test application available on GitHub


November 03, 2019 10:00 PM

Processes…

by Ivar Grimstad at November 03, 2019 09:11 AM

It has been a lot of talk about processes in the Jakarta and MicroProfile community lately, so I just want to remind us all about this item from the Agile Manifesto.

Individuals and interactions over processes and tools.

https://agilemanifesto.org/


That said, some process is needed. Especially for work with specifications. In this post, I explain the Jakarta EE Specification Process and also think aloud about how the same principles could be applied to Eclipse MicroProfile.

The Jakarta EE Specification Process (JESP) is derived from the Foundation Specification Process (EFSP). The short version is that it specifies how long the voting periods (ballots) are for the various reviews:

  • Creation Review: 7 days
  • Plan Review: 7 days
  • Progress Review: 14 days
  • Release Review: 14 days
  • Service Release Review: 14 days

The entire process is visualized in the figure below.

Eclipse Foundation Specification Process (EFSP)

So, how fast can you develop a specification using the JESP?
Well, you will need to come up with a specification project proposal and submit it for review. This review may take up to 7 days to be finalized.

The next step is to present the release plan for the Jakarta EE Specification Committee for a Plan Review. This step is optional and meant as a means for the project to secure that you are on the right track. Let’s say we opt-in for this review which means another 7 days, i.e. 14 in total so far.

When your specification is ready to be released, you will submit it for a release review. This will take 14 days to complete and may run in parallel with the ratification by the Jakarta EE Specification Committee. The total amount of days in review for your specification will then be 28 days.

Without the plan review, we are looking at 21 days which is exactly the same as for any project following the Eclipse Development Process (EDP). Which applies to the e.g. the Eclipse MicroProfile project.

The difference between the governance model of Jakarta EE and Eclipse MicroProfile is that Jakarta EE is a working group and has a specification process in place for capturing the intellectual property before a specification is released. Whereas Eclipse MicroProfile is a standard Eclipse Foundation project with an ad-hoc specification process. As an Eclipse Foundation project, the project name has to be prefixed with Eclipse. As a working group, this restriction does not apply.

In the table below, I have summarized some of the similarities and differences and even taken the liberty to draw up how it could look like if a MicroProfile working group with its own specification process was established.

Jakarta EEEclipse MicroProfile
(as a project)
MicroProfile
(as a working group)
Specification ProcessJESPnoMSP (*)
Development ProcessEDPEDPEDP
Release Review14 days14 days14 days
Ratificationyesnoyes
Working Groupyesnoyes
Project NamesJakarta [spec]Eclipse MicroProfile [spec]MicroProfile [spec]
Specs Consumable by Jakarta EEyesnoyes
Specs Consumable by Eclipse MicroProfileyesyesyes

(*) Thinking aloud: MicroProfile Specification Process (MSP)

The MicroProfile Specification Process could be as simple as this: Adopt the EFSP with the following voting periods (ballots):
(…still thinking aloud…)

  • Creation Review: 7 days (as today according to the EDP)
  • Plan Review: 7 days (or optional as today)
  • Progress Review: 7 days
  • Release Review: 14 days
  • Service Release Review: 14 days

To sum up, I think the JESP has captured the essence of “Individuals and interactions over processes and tools” by being as lightweight as possible while still protecting everyone involved.


by Ivar Grimstad at November 03, 2019 09:11 AM

Building Microservices with Jakarta EE and MicroProfile @ EclipseCon 2019

by Edwin Derks at November 01, 2019 09:02 AM

This year’s EclipseCon was my second time visiting, and simultaneously speaking at this conference. Aside from all the amazing projects that are active within the Eclipse Foundation, this year’s edition contained a long anticipated present: the release of Jakarta EE 8. Reason enough for me and two colleagues to provide a workshop where attendees could actually get hands-on with Jakarta EE 8 and it’s microservices-enabling cousin: Eclipse MicroProfile.

This workshop focusses not only on the various API’s that are provided by Jakarta EE and MicroProfile, but also on development with the Payara application server and how this all fits in a containerised environment.

The slides of the workshop can be found here:

Of course, we hope to evolve this workshop in order to get hands on with new Jakarta EE and MicroProfile features in the near future. Stay tuned!


by Edwin Derks at November 01, 2019 09:02 AM

Java EE - Jakarta EE Initializr

October 25, 2019 10:07 PM

Getting started with Jakarta EE just became even easier!

Get started

Update!

New Archtetype with JakartaEE 8

JakartaEE 8 + Payara 5.193.1 + MicroProfile 3.1 running on Java 11


October 25, 2019 10:07 PM

JakartaEE 8 + Payara 5 + MicroProfile 3 + Docker In about a minute

October 25, 2019 09:40 PM

Thin Wars to the rescue

It can be really easy to start on your JakartaEE application. It’ll take you about a minute…

In this minute you will get a project with:

  • JakartaEE 8
  • MicroProfile 3.1
  • Preconfigured Payara 5 Full server docker container - ivonet/payara
  • Maven essential setup
  • Run and build scripts for all of this

The minute has started…

Enter the code below in a terminal were you want to create your project and press enter

1
2
3
4
mvn archetype:generate \
-DarchetypeGroupId=nl.ivonet \
-DarchetypeArtifactId=jakartaee8-payara-microprofile-archetype \
-DarchetypeVersion=1.0 -U

The first time you run this command, it will take just a bit more time as it will
download everything needed from the maven central repository.

you will be asked these questions:

1
2
3
4
5
Define value for property 'groupId': com.example
Define value for property 'artifactId': helloworld
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' com.example: :
Define value for property 'docker-hub-name': example

Just follow the instructions and your project will be created:

1
2
cd helloworld
./run

This will start the project in a docker container.
The docker container will be downloaded the first time and that might take more than the minute depending
on the speed of your internet connection.
After the first time it will only take seconds.

Now go to http://localhost:8080//rest/example and you will have a working
example HelloWorld application.

Done 😄

After burner

Now you can load it into your favorite IDE and start building your own stuff.
Don’t forget to read the README.md of the project to learn more about the available commands.

Have fun.

Links


October 25, 2019 09:40 PM

Bootstrap a Jakarta EE 8 Maven project with Java 11 in seconds

by rieckpil at October 25, 2019 06:03 AM

In one of my previous blog posts, I showed you what you need to create your first Jakarta EE 8 project. Manually creating a Maven project for a Jakarta EE application from scratch is cumbersome. Especially for new developers, the folder and file setup might be overwhelming. To overcome this manual process and to quickly bootstrap a new Jakarta EE 8 Maven project in seconds, I’ve created a Maven archetype. This includes all the necessary ingredients (Java 11, MicroProfile, JUnit, Mockito, etc.) to kickstart your new project.

Read this blog post to understand how to use this archetype and bootstrap your new Jakarta EE 8 projects in seconds.

Bootstrap a new project with a Maven archetype

First, you need Maven (at least version 3) available on your machine. You can download Maven here and just have to put the Maven binary on your path. Next, open a terminal window and use the following command to create the project:

mvn archetype:generate \
  -DarchetypeGroupId=de.rieckpil.archetypes \
  -DarchetypeArtifactId=jakartaee8 \
  -DarchetypeVersion=1.0.0 \
  -DgroupId=de.rieckpil.blog \
  -DartifactId=jakartaee-8-project \
  -DinteractiveMode=false

HINT: Double-click on the code above to get the raw result to copy and paste it without any additional formatting.

You don’t need to download anything in advance, as this command will download everything from Sonatype. It’s important to specify the correct archetypeGroupId, archetypeArtifactId, archetypeVersion like in the example above.

Both the groupId and the artifactId are free to choose. As a basic convention, I’ll use the artifactId for the folder name and the groupId for the initial package structure.

The interactiveMode attribute is optional but speeds up the process. Otherwise, you need to further confirm the creation of the project.

So the basic usage of this Maven archetype is the following:

mvn archetype:generate -DarchetypeGroupId=de.rieckpil.archetypes \
    -DarchetypeArtifactId=jakartaee8 \
    -DarchetypeVersion=1.0.0\
    -DgroupId=<your project Group Id> \
    -DartifactId=<your project artifact Id>

Components of the pre-defined Jakarta EE 8 project

For the initial components of this Jakarta EE 8 project, I try to keep it to the bare minimum.  Alongside the Jakarta EE and MicroProfile specifications, JUnit 5 and Mocktio are available for efficient testing. Without further configurations, the pom.xml of the project looks like the following:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>de.rieckpil.blog</groupId>
   <artifactId>jakartaee-8-project</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>war</packaging>

   <properties>
      <maven.compiler.source>11</maven.compiler.source>
      <maven.compiler.target>11</maven.compiler.target>
      <failOnMissingWebXml>false</failOnMissingWebXml>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <jakarta.jakartaee-api.version>8.0.0</jakarta.jakartaee-api.version>
      <microprofile.version>3.0</microprofile.version>
      <mockito-core.version>3.1.0</mockito-core.version>
      <junit-jupiter.version>5.5.0</junit-jupiter.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>jakarta.platform</groupId>
         <artifactId>jakarta.jakartaee-api</artifactId>
         <version>${jakarta.jakartaee-api.version}</version>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>org.eclipse.microprofile</groupId>
         <artifactId>microprofile</artifactId>
         <version>${microprofile.version}</version>
         <type>pom</type>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>org.junit.jupiter</groupId>
         <artifactId>junit-jupiter</artifactId>
         <version>${junit-jupiter.version}</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.mockito</groupId>
         <artifactId>mockito-core</artifactId>
         <version>${mockito-core.version}</version>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <finalName>jakartaee-8-project</finalName>
      <plugins>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
         </plugin>
         <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.2</version>
         </plugin>
      </plugins>
   </build>
</project>

Furthermore, the project includes a basic persistence.xml, microprofile-config.properties, beans.xml file to start using JPA, CDI and MicroProfile Config.

In addition a first JAX-RS resource is available to ensure the package structure is created and the application is up- and running:

@ApplicationPath("resources")
public class JAXRSConfiguration extends Application {

}

@Path("sample")
public class SampleResource {

  @Inject
  @ConfigProperty(name = "message")
  private String message;

  @GET
  public Response message() {
    return Response.ok(message).build();
  }

}

Build and deploy the application

As a default deployment target, you’ll get Open Liberty. The project includes a Dockerfile to create a Docker container of your application running on Open Liberty:

FROM open-liberty:kernel-java11
COPY --chown=1001:0  target/jakartaee-8-project.war /config/dropins/
COPY --chown=1001:0  server.xml /config

The configuration for Open Liberty is basic, but enough and can be extended or reconfigured at any time:

<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

    <featureManager>
        <feature>javaee-8.0</feature>
        <feature>microProfile-3.0</feature>
    </featureManager>

    <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443"/>

    <quickStartSecurity userName="duke" userPassword="dukeduke"/>
</server>

HINT: For production usage, make sure to further adjust the security settings properly.

To serve the application from the root path, I’m including a ibm-web-ext.xml file with to configure the context root path:

<web-ext
        xmlns="http://websphere.ibm.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd"
        version="1.0">
    <context-root uri="/"/>
</web-ext>

Last but not least, you can build and deploy the application with a script for convenience. It’s available for both Windows buildAndRun.bat) and Mac/Linux (buildAndRun.sh). Once you execute it, Maven will create the .war file and a new Docker container is spawned.

Once the application is up- and running, you can visit http://localhost:9080/resources/sample and should get a greeting.

In total, these are the required commands to have your next Jakarta EE 8 Maven project up in seconds:

mvn archetype:generate -DarchetypeGroupId=de.rieckpil.archetypes -DarchetypeArtifactId=jakartaee8 -DarchetypeVersion=1.0.0 -DgroupId=de.rieckpil.blog -DartifactId=jakartaee-8-microservice -DinteractiveMode=false
cd jakartaee-8-microservice
./buildAndRun.sh

Live demo of this Jakarta EE 8 archetype

If you are looking for further Maven archetypes to bootstrap a Java EE 8 project with or without JSF setup, have a look at the following tutorials:

You can find the archetype on GitHub.

Have fun creating new Jakarta EE 8 projects with Maven,

Phil

The post Bootstrap a Jakarta EE 8 Maven project with Java 11 in seconds appeared first on rieckpil.


by rieckpil at October 25, 2019 06:03 AM

Deploy Jakarta EE application to Google Cloud Platform (GCP) with Kubernetes

by Hayri Cicek at October 24, 2019 08:41 AM

In the last tutorial, we learned how to deploy our Jakarta EE application locally and created our own Docker registry where we deployed our Docker images and today we will learn how to deploy our Jakarta EE application to Google Cloud Platform (GCP) with Kubernetes.

by Hayri Cicek at October 24, 2019 08:41 AM

Payara ServerはJakarta EE 8互換となりました!

by Kenji Hasunuma at October 22, 2019 09:14 AM

このたび、Jakarta EE 8 TCKの約50,000のテストにすべて合格し、Payara Server 5.191.1がJakarta EE 8 Full Profile互換であるとご報告できることを、私たちはとても嬉しく思います。


by Kenji Hasunuma at October 22, 2019 09:14 AM

Migration from Wildfly 10 to Wildfly 18

October 21, 2019 09:00 PM

Usually vendors declares easy migration, provides how-to documentation and even migration tools. But depends on complexity of your application you can stuck with some compatibility issues. Below i will explain my Wildfliy 10 to Wildfliy 18 migration steps.

First of all you can use provided by WF migration tool to migrate configuration files and compatible modules to the needed release:

git clone https://github.com/wildfly/wildfly-server-migration.git
cd ./wildfly-server-migration/
mvn clean install
cd ./dist/standalone/target/
unzip jboss-server-migration-1.8.0.Final-SNAPSHOT.zip
cd ./jboss-server-migration

./jboss-server-migration.sh -s /opt/wildfly-10.1.0.Final -t /opt/wildfly-18.0.0.Final/

Now let's see application level migration issues:

Issue #1:

Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'org.kostenko.STATUS.ACTIVE'

Error above related to the Hibernate 5.2 performance improvement that avoids unnecessary calls to Class.forName(). Solution here is using Java Naming conventions for a constant. (for example rename STATUS to Status) or in case using non-conventional Java constants set the

<property name="hibernate.query.conventional_java_constants" value="false"/>

in your persistence.xml

Issue #2:

java.lang.IllegalArgumentException: ArquillianServletRunner not found. Could not determine ContextRoot from ProtocolMetadata, please contact DeployableContainer developer.

In case using Arquillian you need just update version org.wildfly.arquillian:wildfly-arquillian-container-managed to version 2.2.0.Final

Issue #3:

org.jboss.weld.exceptions.UnsupportedOperationException:
  at org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler.invoke(CombinedInterceptorAndDecoratorStackMethodHandler.java:49)

Seems to old BUG happened and Weld does not support Java 8 default methods completely. So, pity but same refactoring here is needed.

Issue #4:

WFLYRS0018: Explicit usage of Jackson annotation in a JAX-RS deployment; the system will disable JSON-B processing for the current deployment. Consider setting the 'resteasy.preferJacksonOverJsonB' property to 'false' to restore JSON-B.
...
javax.ws.rs.client.ResponseProcessingException: javax.ws.rs.ProcessingException: RESTEASY008200: JSON Binding deserialization error  
  at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:156)  
  at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:473)  
  at org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder.get(ClientInvocationBuilder.java:195)  

Since latest versions, WF uses org.eclipse.yasson as JSON-B provider. It can provoke some compatibility problems in case using different implementations. Solution here is refactoring according to the JSON-B specification or excluding resteasy-json-binding-provider from application class loader by providing WEB-INF/jboss-deployment-structure.xml:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <deployment>
        <exclusions>
            <module name="org.jboss.resteasy.resteasy-json-binding-provider"/>
        </exclusions>
    </deployment>
</jboss-deployment-structure>

or in case using EARs, do exclusion from submodules like

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <deployment>
        <exclusions>
            <module name="org.jboss.resteasy.resteasy-json-binding-provider"/>
        </exclusions>
    </deployment>
    <sub-deployment name="module-1.jar">
        <exclusions>
            <module name="org.jboss.resteasy.resteasy-json-binding-provider"/>
        </exclusions>
    </sub-deployment>    
</jboss-deployment-structure>

Issue #5:
According to the fixed Hibernate BUG, for now JPA call setMaxResult(0) returns empty List instead of ALL elements in previous versions. So, just check it and do some refactoring if needed.


October 21, 2019 09:00 PM

A Tool for Jakarta EE Package Renaming in Binaries

by BJ Hargrave (noreply@blogger.com) at October 17, 2019 09:26 PM

In a previous post, I laid out my thinking on how to approach the package renaming problem which the Jakarta EE community now faces. Regardless of whether the community chooses big bang or incremental, there are still existing artifacts in the world using the Java EE package names that the community will need to use together with the new Jakarta EE package names.

Tools are always important to take the drudgery away from developers. So I have put together a tool prototype which can be used to transform binaries such as individual class files and complete JARs and WARs to rename uses of the Java EE package names to their new Jakarta EE package names.

The tools is rule driven which is nice since the Jakarta EE community still needs to define the actual package renames for Jakarta EE 9. The rules also allow the users to control which class files in a JAR/WAR are transformed. Different users may want different rules depending upon their specific needs. And the tool can be used for any package renaming challenge, not just the specific Jakarta EE package renames.

The tools provides an API allowing it to be embedded in a runtime to dynamically transform class files during the class loader definition process. The API also supports transforming JAR files. A CLI is also provided to allow use from the command line. Ultimately, the tool can be packaged as Gradle and Maven plugins to incorporate in a broader tool chain.

Given that the tool is prototype, and there is much work to be done in the Jakarta EE community regarding the package renames, I have started a list of TODOs in the project' issues for known work items.

Please try out the tool and let me know what you think. I am hoping that tooling such as this will ease the community cost of dealing with the package renames in Jakarta EE.

PS. Package renaming in source code is also something the community will need to deal with. But most IDEs are pretty good at this sort of thing, so I think there is probably sufficient tooling in existence for handling the package renames in source code.

by BJ Hargrave (noreply@blogger.com) at October 17, 2019 09:26 PM

Relationship between Payara Platform, MicroProfile and Java EE/Jakarta EE

by Rudy De Busscher at October 15, 2019 11:27 AM

Maybe you've already heard about Eclipse MicroProfile, or maybe you don't know what benefits it offers you in your current project. Perhaps you don't see the relationship with Java EE/Jakarta EE - or how you can use it with Payara Server or Payara Micro.

In this blog, I'll give you a short overview of all of the above questions so that you can start using MicroProfile in your next project on the Payara Platform.


by Rudy De Busscher at October 15, 2019 11:27 AM

Deploy Jakarta EE application to Kubernetes

by Hayri Cicek at October 14, 2019 06:42 AM

In this tutorial, I will show you how to deploy Jakarta EE application to Kubernetes.
Kubernetes doesn't run containers directly, instead it uses something called pod, which is a group of containers deployed together on the same host.
To follow this tutorial, you will need Docker, Kubernetes, Maven and of course Java installed on your machine.
I will use my custom maven archetype to generate the Jakarta EE application.


by Hayri Cicek at October 14, 2019 06:42 AM

Jakarta EE and MicroProfile applications with React and PostgreSQL

by rieckpil at October 12, 2019 02:37 PM

As now all major application server vendors are Jakarta EE 8 certified, we are ready to start a new era of enterprise Java. Most of the examples on the internet lack a full-stack approach and just focus on the backend. With this post, I want to share a simple full-stack example following best practices with Jakarta EE, MicroProfile,  React, and PostgreSQL. This includes a Flyway setup to migrate the database schema and TypeScript for the frontend application. At the end of this blog post, you’ll be able to connect your React application to a Jakarta EE & MicroProfile backend to display data from PostgreSQL.

Setup the backend for Jakarta EE and MicroProfile

The backend uses Java 11 and Maven and to build the project. Next to the Jakarta EE and MicroProfile dependencies, I’m adding the PostgreSQL driver and Flyway for the schema migration:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>de.rieckpil.blog</groupId>
    <artifactId>guide-to-jakarta-ee-with-react-and-postgresql</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <!-- configure the version numbers -->
    </properties>

    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>${jakarta.jakartaee-api.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.microprofile</groupId>
            <artifactId>microprofile</artifactId>
            <version>${microprofile.version}</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>${postgresql.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
            <version>${flyway-core.version}</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>guide-to-jakarta-ee-with-react-and-postgresql</finalName>
    </build>
</project>

The backend exposes one REST endpoint to retrieve all available books inside the database. To show you the MicroProfile integration inside a Jakarta EE application, I’m injecting a config property to limit the number of books:

@Path("books")
public class BookResource {

    @Inject
    @ConfigProperty(name = "book_list_size", defaultValue = "10")
    private Integer bookListSize;

    @PersistenceContext
    private EntityManager entityManager;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAllBooks() {

        List<Book> allBooks = this.entityManager
                .createQuery("SELECT b FROM Book b", Book.class)
                .setMaxResults(bookListSize)
                .getResultList();

        return Response.ok(allBooks).build();
    }
}

The JPA Book entity looks like the following:

@Entity
public class Book {

    @Id
    @GeneratedValue
    private Long id;

    private String title;
    private String author;
    private String excerpt;
    private String isbn;
    private String genre;
    private LocalDateTime published;
 
    // ... getters & setters
}

Furthermore, as the frontend application will, later on, run on a different port, we have to add a CORS filter for the JAX-RS resource:

@Provider
public class CorsFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext,
                       ContainerResponseContext responseContext) throws IOException {
        responseContext.getHeaders()
          .add("Access-Control-Allow-Origin", "*");
        responseContext.getHeaders()
          .add("Access-Control-Allow-Credentials", "true");
        responseContext.getHeaders()
          .add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
        responseContext.getHeaders()
          .add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }
}

Prepare the PostgreSQL database schema with Flyway

Flyway is a Java library to version your database schema and evolve it over time. For the schema migration I’m using a singleton EJB with the @Startup annotation to make sure the schema is updated only once:

@Startup
@Singleton
@TransactionManagement(TransactionManagementType.BEAN)
public class FlywayUpdater {

    @Resource(lookup = "jdbc/postgresql")
    private DataSource dataSource;

    @PostConstruct
    public void initFlyway() {
        System.out.println("Starting to migrate the database schema with Flyway");
        Flyway flyway = Flyway.configure().dataSource(dataSource).load();
        flyway.migrate();
        System.out.println("Successfully applied latest schema changes");
    }
}

It’s important to set the transaction management for this class to TransactionManagementType.Bean. This will delegate the transaction handling to the bean and not the container. Besides the normal Jakarta EE transaction management, where the application server takes care of committing and rollback, Flyway will do it itself.

With this setup, Flyway will evaluate the schema version on every application startup. New schema changes are then applied to PostgreSQL if required. There are further ways to migrate the database schema with Flyway using a CLI or Maven Plugin.

For this simple example, I’m using two database scripts: one to create the table for the Book entity :

CREATE TABLE book (
    id BIGINT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    excerpt TEXT,
    author VARCHAR(255) NOT NULL,
    isbn VARCHAR (20) NOT NULL,
    genre VARCHAR(255),
    published TIMESTAMP
);

… and another script to populate some books:

INSERT INTO book VALUES (1, 'Jakarta EE 8', 'All you need to know about Jakarta EE 8', 'Duke', '...', 'Java', '...');
INSERT INTO book VALUES (2, 'React 16', 'Effective Frontend Development with React', 'Duke', '...', 'React', '...');
INSERT INTO book VALUES (3, 'MicroProfile 3', 'All you need to know about Jakarta EE 8', 'Duke', '...', 'Java', '...');
INSERT INTO book VALUES (4, 'Jakarta EE 9', 'All you need to know about Jakarta EE 8', 'Duke', '...', 'Java', null);

Important note: Please make sure to add an empty flyway.location file to the folder of your migrations script (in this example /src/main/resources/db/migration) to use Flyway with Open Liberty.

Prepare Open Liberty for PostgreSQL

The Open Liberty application server recently announced (since 19.0.0.7) its first-class support for PostgreSQL. With this, the configuration of the JDBC data source requires a little bit less XML code.

We still have to provide the JDBC driver for PostgreSQL and link to it in the server.xml file. As I’m using Docker for this example, I’m extending the default Open Liberty image to add the custom server.xml and the JDBC driver. You can find the latest JDBC driver for PostgreSQL on Maven Central.

FROM open-liberty:kernel-java11
COPY --chown=1001:0 postgresql-42.2.8.jar /opt/ol/wlp/lib/
COPY --chown=1001:0 target/guide-to-jakarta-ee-with-react-and-postgresql.war /config/dropins/
COPY --chown=1001:0 server.xml /config

Next, we configure Open Liberty for MicroProfile 3.0 & Jakarta EE 8 (the javaee-8.0 feature works for Jakarta EE as well) and our PostgreSQL data source :

<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

    <featureManager>
        <feature>javaee-8.0</feature>
        <feature>microProfile-3.0</feature>
    </featureManager>

    <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443"/>

    <quickStartSecurity userName="duke" userPassword="dukeduke"/>

    <dataSource id="DefaultDataSource" jndiName="jdbc/postgresql">
        <jdbcDriver libraryRef="postgresql-library"/>
        <properties.postgresql serverName="book-store"
                               portNumber="5432"
                               databaseName="postgres"
                               user="postgres"
                               password="postgres"/>
    </dataSource>

    <library id="postgresql-library">
        <fileset dir="/opt/ol/wlp/lib"/>
    </library>
</server>

Make sure to add the DefaultDataSource as an id for the dataSource configuration, so JPA will take it without any further configuration.

PS: If you are looking for a reference guide to set up the JDBC data source on a different application server, have a look at this cheat sheet.

Create the React application with TypeScript

For this example, React and TypeScript is used to create the frontend application. To bootstrap a new React application with TypeScript you can use create-react-app as the following:

npx create-react-app my-app --typescript

This creates a new React project with everything you need to start. In addition, I’ve added semantic-ui-react to get some pre-built components:

npm install semantic-ui-react
npm install semantic-ui-css

The TypeScript types are already included in the packages above and you don’t have to install anything else.

Next, we can start by creating the React components for this application. To reduce complexity, I’ll just use the already provided App component and a BookTable component. The App is going to fetch the data from our Jakarta EE backend and pass it to the BookTable component to render the data inside a table.

Both components are functional components and the data is fetched with a React Effect Hook and the Fetch browser API:

const App: React.FC = () => {

    const [data, setData] = useState<Array<Book> | Error>();
    useEffect(() => {
        fetch('http://localhost:9080/resources/books')
            .then(response => response.json() as Promise<Book[]>)
            .then(data => setData(data))
            .catch(error => setData(new Error(error.statusText)))
    }, []);

    let content;

    if (!data) {
        content = <Message>Loading</Message>;
    } else if (data instanceof Error) {
        content = <Message negative>An error occurred while fetching the data</Message>;
    } else {
        content = <BookTable books={data}></BookTable>;
    }

    return (
        <Container>
            <Header as='h2'>Available Books</Header>
            {content}
        </Container>
    );
}

export default App;

Inside the BookTable we can use the Table component from semantic-ui-react to render the result:

export const BookTable: React.FC<BookTableProps> = ({books}) => {
    return (
        <Table celled>
            <Table.Header>
                <Table.Row>
                    <Table.HeaderCell>ID</Table.HeaderCell>
                    <Table.HeaderCell>Title</Table.HeaderCell>
                    <Table.HeaderCell>Genre</Table.HeaderCell>
                    <Table.HeaderCell>Excerpt</Table.HeaderCell>
                    <Table.HeaderCell>ISBN</Table.HeaderCell>
                    <Table.HeaderCell>Published</Table.HeaderCell>
                </Table.Row>
            </Table.Header>
            <Table.Body>
                {books.map(book =>
                    <Table.Row key={book.id}>
                        <Table.Cell>{book.id}</Table.Cell>
                        <Table.Cell>{book.title}</Table.Cell>
                        <Table.Cell>{book.genre}</Table.Cell>
                        <Table.Cell>{book.excerpt}</Table.Cell>
                        <Table.Cell>{book.isbn}</Table.Cell>
                        <Table.Cell>{book.published}</Table.Cell>
                    </Table.Row>
                )}
            </Table.Body>
        </Table>
    );
};

For the frontend deployment, I’m using an nginx Docker image and copy the static files to it:

FROM nginx:1.17.4
COPY build /usr/share/nginx/html

The final result of Jakarta EE, MicroProfile, React and PostgreSQL

Once everything is up- and running, the frontend should look like the following:

React Table filled by Jakarta EE backend

You can find the whole source code on GitHub and instructions to deploy the example on your local machine.

If you are looking for further quickstart examples like this, have a look at my Common Enterprise Use Case overview.

Have fun creating Jakarta EE & MicroProfile applications with React and PostgreSQL,

Phil

The post Jakarta EE and MicroProfile applications with React and PostgreSQL appeared first on rieckpil.


by rieckpil at October 12, 2019 02:37 PM

Signing in…

by Ivar Grimstad at October 12, 2019 12:49 PM

It’s been a week since I started as the Jakarta EE Developer Advocate at the Eclipse Foundation!

As you may have noticed, I am involved in almost any committee around Jakarta EE and enterprise Java in general and my new role has some implications for these engagements. I have listed them below and tried to give a reasonable explanation for each of them.

EE4J PMC

I have been a member of the EE4J PMC since its inception back in 2017, and for practical reasons served as the PMC Lead the entire time. According to the charter, we are supposed to rotate the leadership among the non-foundation staff members of the PMC. In order to minimize overhead, the PMC decided to stick with me as the lead until otherwise decided.

If the PMC wants me to continue in the PMC Lead position, the “non-Foundation staff” phrase will have to be removed from the charter. This has been put on the agenda for the PMC meeting on November 5th, so then we will know…

Jakarta EE Working Group Steering Committee

I have withdrawn from my elected Committer Representative seat in the Steering Group as this seat should not be held by anyone from the Eclipse Foundation. This position is currently up for election (hint hint: if you want to be involved, nominate yourself…).

Jakarta EE Working Group Specification Committee

The position I have in the Specification Committee is the PMC Representative. It is up to the PMC whether I should continue or withdraw. This will also be handled at the next PMC meeting on November 5th.

Java Community Process (JCP) Executive Committee

I have withdrawn from my Associate Seat at the JCP since the Eclipse Foundation is already on the committee. However, I will still be lurking around here as I will be the alternate representative for the Eclipse Foundation.

The JCP Elections have started. Remember to cast your vote!

by Ivar Grimstad at October 12, 2019 12:49 PM

Back from Oracle Code One 2019

by Jean-François James at October 10, 2019 03:01 PM

From September 15 to 19, I had the chance to participate in the event Oracle Code One San Francisco as a speaker. Here is my feedback. What is Oracle Code One? Oracle Code One San Francisco is one of the leading annual international meeting for developers. It is organized in parallel to another major event, […]

by Jean-François James at October 10, 2019 03:01 PM

Jakarta EE Community Update October 2019

by Tanja Obradovic at October 09, 2019 05:07 PM

Welcome to the latest Jakarta EE community update. In this edition, we highlight key opportunities to participate in upcoming community events, explore the Jakarta EE 8 release, and learn more about the very bright future of cloud native Java.

EclipseCon Europe 2019: Register for Community Day

Community Day, which will be held Monday, October 21 at EclipseCon Europe, is a must for everyone who’s interested in our cloud native projects. The day is dedicated to community-organized meetings to discuss projects and technologies, provide workshops and coding sessions, hold working group gatherings, and more. Lunch and breaks are included, and the day ends with a casual reception.

There’s already a gathering planned for anyone interested in Jakarta EE, MicroProfile, Eclipse Jemo, Eclipse Che, Eclipse Codewind, and other cloud-related topics. To see the agenda so far, and add your ideas for discussion topics, check the EclipseCon Europe Community Day wiki.

 And, don’t forget to attend our new event this year — Community Evening on Tuesday, October 22. This is your opportunity to participate in more casual, interactive events and enjoy a beverage with your community colleagues. A bar offering beer, wine, water, and juice will be available. 

To register for EclipseCon Europe and for Community Day, click here.

__________________________

 JakartaOne Livestream Wrap-Up

The first-ever JakartaOne Livestream event was a huge success with more than 1,400 registered attendees. The online conference, held September 10, marked the release of the first vendor-neutral, Java EE 8-compatible release of Jakarta EE following the new Jakarta EE Specification Process.

We first knew this event would be bigger than expected when several well-respected leaders in the Java EE community graciously and enthusiastically agreed to join the JakartaOne Livestream Program Committee. Led by Committee Chair, Reza Rahman, committee members Adam Bien, Ivar Grimstad, Arun Gupta, Josh Juneau, along with Tanja Obradovic from the Eclipse Foundation, put in a huge effort to plan the conference.

One of the committees’ toughest jobs was selecting 16 conference papers for presentation from among the more than 50 high-quality submissions. Participants enjoyed a great mixture of introductory and overview sessions, including sessions on particular specifications, cloud native topics, keynotes from Mike Milinkovich and James Gosling, as well as industry keynotes from Jakarta EE Working Group Steering Committee members IBM, Fujitsu, Oracle, Payara, Red Hat, and Tomitribe. Demos, panel discussions, and Q&A sessions rounded out the 18 hours of program material that were delivered.

To see a list of the topics presented and access the session recordings, visit jakartaone.org.    

__________________________

Jakarta EE 8 Release Highlights

The Jakarta EE 8 release is now available with 43 projects, more than 60 million lines of code, and full compatibility with Java EE 8.

 With the delivery of the Jakarta EE 8 Platform, the entire ecosystem — from software vendors to developers and enterprises — has all of the pieces needed to shape the future of cloud native Java and meet the modern enterprise’s need for cloud-based applications that resolve key business challenges.

To ensure that cloud native Java applications are portable, secure, stable, and resilient, product compatibility certifications are underway. We already have three products that are certified as compatible with the full Jakarta EE 8 platform:

·      Eclipse GlassFish application server, version 5.1

·      IBM Open Liberty server runtime, version 19.0

·      Red Hat WildFly application server, version 17.0

Eclipse GlassFish and Open Liberty are also certified as Jakarta EE 8 web profile-compatible products.

Almost three dozen Jakarta EE specifications are also available. Jakarta projects are listed here and are included in our main project repository. It’s time for everyone to get involved in the cloud native Java community and engage in turning the huge potential for cloud native Java into reality.

__________________________

Our Free Cloud Native Java E-Book Is Now Available

To mark the significance of the Jakarta EE 8 release, we also released a free e-book, Fulfilling the Vision for Open Source, Cloud Native Java, on September 10. The e-book includes insights from some of the leading voices in enterprise Java and the Jakarta EE Working Group. It explores:

·      Why the world needs open source, cloud native Java

·      The common vision for cloud native Java that has emerged

·      The many benefits of cloud native Java for software vendors, developers, and enterprises

·      Why it’s time for all Java stakeholders to get involved in the Jakarta EE Working Group

·      Priorities for evolving cloud native Java in the short- and long-term

·      The vital role of the Eclipse Foundation in supporting cloud native Java evolution

 Download the e-book today.

__________________________

A Look Back at September Events

September was a busy month for Jakarta EE and cloud native Java events as we participated in the JakartaOne Livestream event, described earlier, as well as Oracle Code One and HeapCon. Check out the blogs about Oracle Code One by Payara and Tomitribe.

 A quick note about Oracle Code One: Everyone at the Eclipse Foundation was extremely proud when our executive director, Mike Milinkovich, accepted the Duke’s Choice Award on behalf of the Jakarta EE community at the conference.

__________________________

Stay Connected With the Jakarta EE Community

The Jakarta EE community promises to be very active and there are a number of channels to help you stay up to date with all of the latest and greatest news and information. Tanja Obradovic’s blog offers a sneak peek at the community engagement plan, which includes:

·      Social media: Twitter, Facebook, LinkedIn Group

·      Mailing lists: jakarta.ee-community@eclipse.org and jakarta.ee-wg@eclipse.org

·      Newsletters, blogs, and emails: Eclipse newsletter, Jakarta EE blogs, monthly update emails to jakarta.ee-community@eclipse.org, and community blogs on “how are you involved with Jakarta EE”

·      Meetings: Jakarta Tech Talks, Jakarta EE Update, Jakarta Town Hall, and Eclipse Foundation events and conferences, such as EclipseCon Europe

Subscribe to your preferred channels today. And, get involved in the Jakarta EE Working Group to help shape the future of open source, cloud native Java. To learn more about Jakarta EE-related plans and check the date for the next Jakarta Tech Talk, be sure to bookmark the Jakarta EE Community Calendar.


by Tanja Obradovic at October 09, 2019 05:07 PM

Payara Server is Jakarta EE 8 Compatible!

by Patrik Duditš at October 09, 2019 11:00 AM

We are very happy to report that we've successfully passed all of nearly 50,000 test suites of Jakarta EE 8 TCK, and Payara Server 5.193.1 is Jakarta EE 8 Full Profile compatible!


by Patrik Duditš at October 09, 2019 11:00 AM

Contexts and Dependency Injection (CDI) – A specification introduction

by rieckpil at October 07, 2019 09:07 AM

Dependency Injection (DI) is one of the central techniques in today’s applications and targets Separation of concerns. Not only makes this testing easier, but you are also not in charge to know how to construct the instance of a requested class. With Java/Jakarta EE we have a specification which (besides other topics) covers this: Contexts and Dependency Injection (short CDI). CDI is also part of the Eclipse MicroProfile project and many other Java/Jakarta EE specifications already use it internally or plan to use it.

Learn more about the Contexts and Dependency Injection (CDI) specification, its annotations and how to use it in this blog post. Please note that I won’t cover every aspect of this spec and rather concentrate on the most important parts. For more in-depth knowledge, have a look at the following book.

Specification profile: Contexts and Dependency Injection (CDI)

  • Current version: 2.0 in Java/Jakarta EE 8 and 2.0 in MicroProfile 3.0
  • GitHub repository
  • Specification homepage
  • Basic use case: provide a typesafe dependency injection mechanism

Basic dependency injection with CDI

The main use case for CDI is to provide a typesafe dependency injection mechanism. To make a Java class injectable and managed by the CDI container, you just need a default no-args constructor or a constructor with a @Inject annotation.

If you use no further annotations, you have to tell CDI to scan your project for all available beans. You can achieve this which a beans.xml file inside src/main/resources/webapp/WEB-INF using the bean-discovery-mode:

<?xml version="1.0" encoding="UTF-8"?>
<beans 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/beans_1_1.xsd"
       bean-discovery-mode="all">
</beans>

Using this setup, the following BookService can inject an instance of the IsbnValidator class:

public class IsbnValidator {
    public boolean validateIsbn(String isbn) {
        return isbn.replace("-", "").length() < 13);
    }
}

public class BookService {

    @Inject
    private IsbnValidator isbnValidator;

    // work with the instance
}

You can inject beans via either field-, setter-, constructor-injection or request a bean manually from the CDI runtime:

public void storeBook(String bookName, String isbn) {
   if (CDI.current().select(IsbnValidator.class).get().validateIsbn(isbn)) {
        logger.info("Store book with name: " + bookName);
   }
}

Once CDI manages a bean, the instances have a well-defined lifecycle and are bound to a scope. You can interact with the lifecycle of a bean while using e.g. @PostConstruct or @PreDestroy. The default scope, if you don’t specify any (like in the example above), is the pseudo-scope @Dependent. With this scope, an instance of your bean is bound to the scope of the bean it gets injected to and won’t be shared.

However, you can specify the scope of your bean using the available scopes in CDI:

  • @RequestScoped – bound to an HTTP request
  • @SessionScoped – bound to the HTTP session of a user
  • @ApplicationScoped – like a Singleton, one instance per application
  • @ConversationScoped – bound to a conversation context e.g. wizard-like web app

If you need a more dynamic approach for creating a bean that is managed by CDI you can use the @Produces annotation. This gives you access to the InjectionPoint which contains metadata about the class who requested an instance:

public class LoggerProducer {

    @Produces
    public Logger produceLogger(InjectionPoint injectionPoint) {
        return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
    }
}

Using qualifiers to specify beans

In the previous chapter, we looked at the simplest scenario where we just have one possible bean to inject. Imagine the following scenario where have multiple implementations of an interface:

public interface BookDistributor {
    void distributeBook(String bookName);
}

public class BookPlaneDistributor implements BookDistributor {

    @Override
    public void distributeBook(String bookName) {
        System.out.println("Distributing book by plane");
    }
}

public class BookShipDistributor implements BookDistributor {

    @Override
    public void distributeBook(String bookName) {
        System.out.println("Distributing book by ship");
    }
}

If we now request a bean of the type BookDistributor, which instance do we get? The BookPlaneDistributor or an instance of BookShipDistributor?

public class BookStorage {

    @Inject // this will fail
    private BookDistributor bookDistributor;

}

… well, we get nothing but an exception, as the CDI runtime doesn’t know which implementation to inject:

WELD-001409: Ambiguous dependencies for type BookDistributor with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private de.rieckpil.blog.qualifiers.BookStorage.bookDistributors
  at de.rieckpil.blog.qualifiers.BookStorage.bookDistributors(BookStorage.java:0)
  Possible dependencies: 
  - Managed Bean [class de.rieckpil.blog.qualifiers.BookShipDistributor] with qualifiers [@Any @Default],
  - Managed Bean [class de.rieckpil.blog.qualifiers.BookPlaneDistributor] with qualifiers [@Any @Default]

The stack trace contains an important hint on how to fix such a scenario. If we don’t further qualify a bean our beans have the default qualifiers @Any and @Default. In the scenario above the BookStorage class requests for a BookDistributor and also does not specify anything else, meaning it will get the @Default bean. As there are two beans with this default behavior, dependency injection is not possible (without further adjustments) here.

To fix the error above, we have to introduce qualifiers and further specify which concrete bean we want. A qualifier is a Java annotation including @Qualifier:

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface PlaneDistributor {
}

Once we have this annotation, we can use it both for the implementation and at the injection point:

@PlaneDistributor
public class BookPlaneDistributor implements BookDistributor {

    @Override
    public void distributeBook(String bookName) {
        System.out.println("Distributing book by plane");
    }
}

@Inject
@PlaneDistributor
private BookDistributor bookPlaneDistributor;

… and now have a proper injection of our requested bean.

Above all, you can also always request for all instances matching a Java type using the Instance<T>  wrapper class:

public class BookStorage {

    @Inject
    private Instance<BookDistributor> bookDistributors;

    public void distributeBookToCustomer(String bookName) {
        bookDistributors.forEach(b -> b.distributeBook(bookName));
    }
}

Enrich functionality with decorators & interceptors

With CDI we have two mechanisms to enrich/extend the functionality of a class without changing the implementation: Decorators and Interceptors.

Decorators allow a type-safe way to decorate your actual implementation. Given the following example of an Account  interface and one implementation:

public interface Account {
    Double getBalance();
    void withdrawMoney(Double amount);
}

public class CustomerAccount implements Account {

    @Override
    public Double getBalance() {
        return 42.0;
    }

    @Override
    public void withdrawMoney(Double amount) {
        System.out.println("Withdraw money from customer: " + amount);
    }
}

We can now write a decorator to make special checks if the amount of money to withdraw meets a threshold:

@Decorator
public abstract class LargeWithdrawDecorator implements Account {

    @Inject
    @Delegate
    private Account account;

    @Override
    public void withdrawMoney(Double amount) {
        if (amount >= 100.0) {
            System.out.println("A large amount of money gets withdrawn!!!");
            // e.g. do further checks
        }
        account.withdrawMoney(amount);
    }
}

With interceptors, we get a more generic approach and don’t have the same method signature as the intercepted class, rather an InvocationContext. This offers more flexibility as we can reuse our interceptor on multiple classes/methods. A lot of cross-cutting logic in Java/Jakarta EE like transactions and security is actually achieved with interceptors. For an example on how to write interceptors, have a look at one of my previous blog posts.

Both decorators and interceptors are inactive by default. To activate them, you either have to specify them in your beans.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans 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/beans_1_1.xsd"
       bean-discovery-mode="all">
    <decorators>
        <class>de.rieckpil.blog.decorators.LargeWithdrawDecorator</class>
    </decorators>
</beans>

or using the @Priority annotation and specify the priority value:

@Decorator
@Priority(100)
public abstract class LargeWithdrawDecorator implements Account {
}

Decouple components with CDI events

Last but not least, the CDI specification provides a sophisticated event notification model. You can use this to decouple your components and use the Observer pattern to notify all listeners once a new event is available.

The event notification in CDI is available both in a synchronous and asynchronous way. The payload of the event can be any Java class and you can use qualifiers to further specialize an event. Firing an event is as simple as the following:

public class BookRequestPublisher {

    @Inject
    private Event<BookRequest> bookRequestEvent;

    public void publishNewRequest() {
        this.bookRequestEvent.fire(new BookRequest("MicroProfile 3.0", 1));
   }
}

Observing such an event requires the @Observes annotation on the receiver-side:

public class BookRequestListener {
    public void onBookRequest(@Observes BookRequest bookRequest) {
        System.out.println("New book request incoming: " + bookRequest.toString());
    }
}

Using the asynchronous way, you receive a CompletionStage<T> as a result and can add further processing steps or handle errors:

public class BookRequestPublisher {

    @Inject
    private Event<BookRequest> bookRequestEvent;

    public void publishNewRequest() {

        this.bookRequestEvent
                .fireAsync(new BookRequest("MicroProfile 3.0", 1))
                .handle((request, error) -> {
                    if (error == null) {
                        System.out.println("Successfully fired async event");
                        return request;
                    } else {
                        System.out.println("Error occured during async event");
                        return null;
                    }
                })
                .thenAccept(r -> System.out.println(r));
    }

}

Listening to async events requires the @ObservesAsync  annotation instead of @Observes :

public void onBookRequestAsync(@ObservesAsync BookRequest bookRequest) {
   System.out.println("New book request incoming async: " + bookRequest.toString());
}

YouTube video for using CDI 2.0 specification

Watch the following YouTube video of my Getting started with Eclipse MicroProfile 3.0 series to see CDI 2.0 in action:

If you are looking for resources to learn more advanced CDI concepts in-depth, have a look at this book.

You can find the source code with further instructions to run this example on GitHub.

Have fun using the CDI specification,

Phil

The post Contexts and Dependency Injection (CDI) – A specification introduction appeared first on rieckpil.


by rieckpil at October 07, 2019 09:07 AM

#REVIEW: Pro CDI 2 in Java EE 8 (book)

by rieckpil at October 05, 2019 10:39 AM

When it comes to creating an application with Java (now Jakarta) EE, the first specification you usually get in touch with is CDI (Contexts and Dependency Injection). Starting with this specification, you’ll probably know it for its dependency injection (DI) capabilities: @Inject. Even besides DI, the CDI spec offers a lot more: events, decorators, interceptors, etc. Well-known books about Java EE (find some of them here) sometimes only cover basic CDI functionality and rarely dedicated more than one chapter for it. Fortunately, Jan Beernink and Arjan Tijms recently published a book to cover the CDI spec in-depth: Pro CDI 2 in Java EE 8 – An In-Depth Guide to Context and Dependency Injection.

proCDI2InJavaEE8BookCover

The whole book consists of 241 pages and is available both as a digital and print version (e.g. on Amazon). I got the PDF version from Arjan and was able to read it in four days while trying out some examples in the IDE in parallel. My CDI knowledge before reading the book was more basic. I was able to use the concepts, but never touched advanced topics and still had some knowledge gaps to connect all the dots. This changed a lot after reading the book!

Let’s start.

The history of CDI

The book starts with a throwback of important people and events in the history of the CDI specification. This was extremely valuable for me, as I wasn’t aware of how everything started and who drove the success of CDI (btw. I am 24 and started with Java EE 7). You’ll learn about how Rod Johnson, Gavin King, and Bob Lee had an influence on CDI. Furthermore, this chapter includes the evolution of the major Java EE specifications with an own dependency injection framework (e.g. JSF, JAX-RS…) alongside CDI and you’ll realize that CDI is a rather young spec, compared to EJB or JPA.

Next, the authors describe the influence of proprietary DI frameworks in the past for CDI and how the AtInject JSR is related to CDI. This chapter is a nice recap of how the specification evolved to a more or less platform DI framework for Java EE, as more and more specifications plan to remove their own injection framework.

CDI beans, scopes and qualifiers

In the following chapters of the Pro CDI 2 book, you get a detailed introduction of what the component model and a CDI bean actually is. This includes a lot of basic knowledge, you need to understand CDI in full execution. You’ll learn about the different ways to identify and retrieve a CDI bean. Next, the authors present all different scopes and when to use them. In addition, they provide two good examples to write your own CDI scope and how to integrate it with a CDI extension.

All of this was really important for me to connect the missing dots, as I always mixed up what @Dependent, @Any, @Qualifier, @Named etc. actually does.

CDI events in the Pro CDI 2 book

Another important aspect of the CDI specification is events. With CDI it’s really easy to emit and observe events to decouple parts of your application. The authors dedicate an own chapter to this topic and explain it in detail. You’ll also get to know how to apply CDI qualifiers to your events to distinguish them. Both synchronous and asynchronous events are covered. For the asynchronous part, you’ll also learn how you can efficiently use the returning CompletionStage<T> to further process or handle errors.

Decorators and interceptors with CDI 2

Next, decorators and interceptors are covered in the Pro CDI 2 book. Even though the interceptor part originates from an own spec, they have a tight integration to CDI. For both of these concepts, the authors provide good examples when to use them and what the main differences are. Aside from creating them, you’ll also learn the ways to activate them and how to put them in order.

For an introduction to CDI interceptors, you can have a look at one of my previous blog post.

Dynamic beans and CDI 2 in Java SE/FX

One of the major advanced CDI topics is Dynamic Beans. The book has an own chapter for covering this and you get examples for both implementing the Bean<T> interface and using a CDI extension alongside a configurator. The authors also emphasize that Dynamic CDI Beans might rarely be a requirement for usual business applications. In contrast, they also provide good examples where it could make sense.

The final chapter of the books gives you an introduction on how to bootstrap CDI in a Java SE and also JavaFX (replacing JavaFX injection) environment. All CDI implementations (e.g. Weld or Apache OpenWebBeans)  supported an API to bootstrap the CDI container in a plain Java SE app for a long time. However, this manual bootstrap API was not standardized until CDI 2. You’ll learn how to include it to your project, scan for beans, and also the differences compared to a Java EE environment. This section also covers how to use this approach for unit testing with JUnit 5.

Summary

To summarize it, I can definitely recommend you to buy and read this book. The authors did great work to produce such an in-depth guide. After reading this book you’ll definitely know everything to effectively use CDI. They balance theoretical, practical and historical explanations in a remarkable way. Their examples always include real-world business problems and are not artificial (like foo & bar). Not only is CDI one of the most central specifications in Java (now Jakarta) EE but also the right use of it makes your development life easier.

Feel free to add a comment if you plan to read it or have something to add.

PS: If you are looking for a reference for basic CDI knowledge, take a look at this introduction to CDI.

Have fun reading this excellent book about CDI 2,

Phil

The post #REVIEW: Pro CDI 2 in Java EE 8 (book) appeared first on rieckpil.


by rieckpil at October 05, 2019 10:39 AM

Configuring Jersey Application

by Jan at October 04, 2019 10:57 PM

It is a common issue, I am asked about every now and then, how to pass the user data to a user application? The user needs to change the code behavior depending on the configuration data. This is where the … Continue reading

by Jan at October 04, 2019 10:57 PM

Back to the top

Submit your event

If you have a community event you would like listed on our events page, please fill out and submit the Event Request form.

Submit Event