David R. Heffelfinger

  Ensode Technology, LLC


Jakarta EE, A de facto standard in the making

I’ve been involved in Java EE since the very beginning, Having written one of the first ever books on Java EE. My involvement in Java EE / Jakarta EE has been on an education / advocacy role. Having written books, articles, blog posts and given talks in conferences about the technology. I advocate Jakarta EE not because I’m paid to do so, but because I really believe it is a great technology. I’m a firm believer that the fact that Jakarta EE is a standard, with multiple competing implementations, results in very high quality implementations, since Jakarta EE avoids vendor lock-in and encourages competition, benefiting developers.

Oracle’s donation of Java EE to the Eclipse Foundation was well received and celebrated by the Java EE community. Many prominent community members had been advocating for a more open process for Java EE, which is exactly what Jakarta EE, under the stewardship from the Eclipse Foundation provides.

There are some fundamental changes on how Jakarta EE is managed, that differ from Java EE, that benefit the Jakarta EE community greatly.

Fundamental differences between Java EE and Jakarta EE Management

Some of the differences in the way Jakarta EE is managed as opposed to Java EE are that there is no single vendor controlling the technology, there is free access to the TCK and there is no reference implementation.

No single company controls the standard

First and foremost, we no longer have a single company as a steward of Jakarta EE. Instead, we have several companies who have a vested interest in the success of the technology working together to develop the standard. This has the benefit that the technology is not subject to the whims of any one vendor, and, if any of the vendors loses interest in Jakarta EE, others can easily pick up the slack. The fact that there is no single vendor behind the technology makes Jakarta EE very resilient, it is here to stay.

TCK freely accessible

Something those of us involved heavily in Jakarta EE (and Java EE before), take for granted, but that may not be clear to others, is that Jakarta EE is a set of specifications with multiple implementations. Since the APIs are defined in a specification, they don’t change across Jakarta EE implementations, making Jakarta EE compliant code portable across implementations. For example, a Jakarta EE compliant application should run with minimal or no modifications on popular Jakarta EE implementations such as Apache Tomee, Payara, IBM’s OpenLiberty or Red Hat’s Thorntail

One major change that Jakarta EE has against Java EE is the fact that the Technology Compatibility Kit (TCK) is open source and free. The TCK is a set of test to verify that a Jakarta EE implementation is 100% compliant with all Jakarta EE specifications. With Java EE, organizations wanting to create a Java EE implementation, had to pay large sums of money to gain access to the TCK, once their implementation passed all the tests, their implementation was certified as Java EE compatible. The fact that the TCK was not freely accessible became a barrier to innovation, as smaller organizations and open source developers not always had the funds to get access to the TCK. Now that the TCK is freely accessible, the floodgates will open, and we should see a lot more quality implementations of Jakarta EE.

No reference implementation

Another major change between Java EE and Jakarta EE is that Java EE had the concept of a reference implementation. The idea behind having a Java EE reference implementation was to prove that suggested API specifications were actually feasible to implement. Having a reference implementation, however, had a side effect. If the reference implementation implemented something that wasn’t properly defined in the specification, then many developers expected all Java EE implementations to behave the same way, making the reference implementation a de-facto Java EE specification of sorts. Jakarta EE does away with the concept of a reference implementation, and will have multiple compatible implementations instead. The fact that there isn’t a reference implementation in Jakarta EE will result in more complete specifications, as differences in behavior between implementations will bring to light deficiencies in the specifications, these deficiencies can then be addressed by the community.


With multiple organizations with a vested interest in Jakarta EE’s success, a lowered barrier of entry for new Jakarta EE implementations, and better specifications Jakarta EE will become the de-facto standard in server-side Java development.


Mitigating Risks of a Microservices Architecture

In the “Demystifying Microservices for Java EE Developers” guide I wrote for Payara, I list several advantages and disadvantages of a microservices architecture. In the guide I list the disadvantages, but don’t really go into how to mitigate or even eliminate the risks. In this post I’ll go over these disadvantages and how to reduce the risks that they present.

Additional operational overhead

When developing an application as a series of microservices, there will be some operational overhead since, instead of deploying one application into production, several small applications (i.e. your microservices) will need to be deployed. To decrease the costs of the operational overhead, a few approaches can be taken.

Deploy to the cloud

When deploying to the cloud, the cloud vendor can provide some of their resources to help with operation tasks for your application, freeing your team from having to perform these tasks. Additionally, most cloud vendors provide elasticity, meaning that your applications can be scaled up or down on demand, as their load increases or decreases, this helps with the scalability of your application as a whole.

Implement a DevOps approach

Your development team assists with operational task such as deployment and monitoring

Use an automated deployment tool

There are several tools in the market that can automate deployments, some free and open source, some commercial. Bamboo and Jenkins are two examples that are popular in the Java world. Puppet is another example, popular with languages typically used with Linux, such as Python or Ruby.

Use an Automated Performance Management (APM) Tool

Monitoring performance becomes a lot harder if you deploy your application as a series of independent modules (microservices). An automated performance management tool can help with this. Some examples include AppDynamics, New Relic, Vector and Prometheus.

Use a log aggregation tool

When deploying an application as a series of microservices, instead of having a single log file to monitor, we typically have several, maybe hundreds of log files to monitor. Doing this by hand is not practical. To mitigate this risk a log aggregation tool such as Splunk, GrayLog or Loggly should be used.

Increased Debugging Complexity

When debugging an application following a microservices architecture, it isn’t always obvious which of your microservices is causing the problem. Some user action (i.e. saving data on an HTML form) could trigger invocations to several microservices, making it harder to pinpoint the cause of the issue.

Additional Tooling

Tools such as log aggregation tools and performance management tools may help.

Implement a policy of collective code ownership

“Collective code ownership” means that nobody owns code, ownership is shared across all teams and all developers in your organization. If a user reports a problem to your team, but it turns out that the problem is not with your code, but with another service that your code depends on, then if there is a policy of collective code ownership your team can fix the problem themselves, instead of waiting for the other team to get around to it.

Correlation Identifiers

When invoking your microservices, generate a correlation id, and pass it around as you invoke your microservices, then have your microservices log the correlation id as they are invoked. This will make it easier to trace microservices invocations when going through log files.

Distributed Transactions

Distributed transactions happen when we start a transaction, and while that transaction is in progress, an invocation to a microservice over the network takes place. Typically we want to avoid distributed transactions as there is a high probability they will timeout and rollback.

Implement your microservices as atomic units

Commit all your transactions before making invocations across the network.

Use compensating transactions

If you commit a transaction that depends on a call to a microservices, and the call fails, then initiate a compensating transaction to revert the changes made by the original transaction.

Susceptibility to the fallacies of distributed computing

L Peter Deutsch came up with the Fallacies of Distributed computing, microservices being inherently distributed, are susceptible to these fallacies.

Implement the circuit breaker design pattern

Modeled after an electrical circuit, the way the circuit breaker design pattern works is that your code attempts to make an invocation over the network, if the call fails, your code retries for a predetermined number of times, if the invocation does not succeed after repeated attempts, then the circuit breaker trips, and your code can handle the failure gracefully (how to do this depends on your specific application requirements).

Use a load balancer

A load balancer such as nginx or F5 can distribute the load across several instances of your services. Most load balancers provide failover capabilities as well.

Deploy to the cloud

The elasticity feature of most cloud providers will help mitigate susceptibility to the fallacies of distributed computing.


Java EE 9 may do away with application servers,should app server vendors be worried?

In my recent article, A glimpse at Java EE’s future, I stated that "Java EE 9 may do away with the concept of application servers completely". This generated some interest on Twitter.

Background - Project Jigsaw and Java Modularity

Some background for those not in the loop, Java 9 will introduce Project Jigsaw, which will bring modularity to the Java platform. Java has been around for some 21 years or so, the JDK includes libraries that are not used a whole lot anymore, for example, libraries to support CORBA, which was popular in the mid to late 90's but is seldom used anymore. However, the JDK team at Oracle is hesitant to remove these libraries because doing so would potentially break compatibility with existing applications that may be using them, therefore newer JDK's need to keep including these old libraries.

Project Jigsaw provides a solution to this problem, instead of including everything in the JDK, from Java 9 and beyond, the JDK will become modular. Applications will use only the modules that they use. Going back to our CORBA example, the few applications out there still using CORBA won't break, but all other applications not using CORBA won't have this unused library lying around. Project Jigsaw will work similarly to the way Maven handles dependencies today, however this functionality will be build right in the JDK.

Project Jigsaw won't be limited to eliminating "cruft" from modern versions of Java, in general, any dependencies an application may have could be declared as a module. Library authors may publish their libraries as modules, which will then be downloaded by any applications that require them at compile time when the application is built.

Modular Java EE

I had the opportunity to attend a Birds of a Feather session titled "Enterprise Java for the Cloud" during JavaOne 2016. During this session is when I heard that there is a possibility that Java EE 9 may do away with the concept of application servers, in favor of Java 9 modules. A very interesting concept and quite a change from the way we have been developing enterprise Java applications since J2EE was released back in 1999. Great news for application developers, but, should application server vendors be worried?

The answer is a resounding no. The way this would work is that vendors would provide their Java EE APIs as modules, then applications would include them as dependencies.  Potentially, this could even benefit application server vendors, let me explain.

As most of you reading this blog probably know, Java EE is a series of specifications, with multiple implementations. For example, Hibernate, EclipseLink and OpenJPA are all implementations of the JPA specification. Similarly, Weld and OpenWebBeans are implementations of the CDI specification. Each application server ships with one implementation of each Java EE specification. As application developers, we are more or less stuck with the implementation that the application server vendor provides (there are ways around this, but they require jumping through hoops). If Java EE 9 adopts the modularity features of Java 9, then we as application developers may be able to pick and choose Java EE API implementations as we please, for example, we could use Hibernate as our JPA implementation, and OpenWebBeans as our CDI implementation (as far as I know, no application server currently provides this combination of CDI and JPA implementations). We as application developers benefit by picking our favorite implementations of each API, and vendors benefit by an increased pool of potential users for their Java EE API implementations.


JavaOne 2016, Day 3, from a Java EE Perspective

Yesterday was day 3 of JavaOne 2016. Oracle and the Java community is planning new features for the upcoming Java EE 8. I've been attending as many Java EE related sessions as I can, to see what the current plans are. All the speakers have made a point to state that nothing is carved in stone, all of this may change as it is still in planning stages.

I started the day attending "Cloud Native Java EE", a tutorial by Payara engineers Mike Croft (@croft) and  Ondrej Mihályi (@OMihalyi). The talk was very good and explained how to deploy Java EE applications to the cloud using Payara Micro.

I then headed over to Antoine Sabot-Durand's (@antoine_sd) session on CDI 2.0. Antoine is the CDI spec lead and obviously knows his stuff. He covered several new features coming to CDI 2.0 such as support for Java SE, asynchronous events, and the ability to add interceptors at runtime to CDI beans. That last one I thought was very impressive, I hadn't ever imagined that would even be possible.

Next I went to a JAX-RS 2.1 session by Ed Burns (@edburns) and Pavel Bucek (@pavel_bucek). The session covered several new JAX-RS features such as non-blocking I/O, server sent events and a reactive client API.

After that I attended "Portable Cloud Applications with Java EE" by Rajiv Mordani, Joe Dipol, Josh Dorr. This session covered how Java EE 9 will standardize the ability to deploy Java EE applications to different cloud providers.

The next session I attended was on Servlet 4.0, delivered by Ed Burns (@edburns), discussing new features of this new version of the Servlet specification. This session started with a brief overview of network programming, Ed took some of us old timers in a trip down memory lane, mentioning things like CGI and Gopher. Of particular interest in this session was Servlet 4.0 support for the HTTP/2 protocol. Ed was very good at explaining how this new version of HTTP addresses several limitations of the current HTTP 1.1 protocol supported by most browsers.

The last session I attended was "Security for Java EE 8 and the Cloud", by Kk Sriramadhesikan. The session covered security challenges posed by cloud environments and how the Java EE spec plans to address it. The new version of the Java EE Security API aims to make it easy for application developers to secure their cloud applications, leaving the details to security experts.

As evidenced by all of these great sessions, major changes are coming to Java EE in the not so distant future, looks like we will have some exciting times ahead.


JavaOne 2016, Day 2 Impressions

This morning I attended Gaurav Gupta's JPA Modeler session, the tool is certainly very impressive and I wanted to learn more about it.

After Gaurav's session, I headed to the Franciscan C/D room to prepare for my own Hands-On Lab, "Java EE, Beyond the Basics". I had some materials (slides, manual, code samples, etc) to copy to the virtual machine's on the laptops and Murphy reared his ugly head. The lab's virtual machines were not booting. I googled the error and learned that as a workaround I had to disable USB on the VMs. With the help of a couple of technicians, we disabled USB on each and every virtual. But I had the files I needed to copy on a thumb drive, how could I copy them with USB disabled? Luckily, I had the files online, therefore we were able to download them and copy them to each and every VM. By the way, all class materials can be downloaded here. Luckily we were able to finish on time, by the time the students showed up the VM's were ready to go.

The session went very well, I covered JSF and EJB, my co-speaker Bob Larsen covered CDI. We were planning to cover JAX-RS as well, but unfortunately we ran out of time. I got some good feedback from the students both face to face and over Twitter, I think the session was well received.

After my session, I attended Linda DeMichiel's session on Java EE 8 Update. Linda, for those that don't know her, is one of the specification leads for the Java EE platform. She covered current plans for Java EE 8, currently scheduled to ship sometime in 2017. A controversial proposal is to drop the MVC API from Java EE 7, as well as JMS 2.1 (JMS 2.0, the current version, would be delivered with Java EE instead).

I then attended "Enterprise Java for the Cloud" by Rajiv Mordani, Josh Dorr and Dhiraj Mutreja. This session was about what is planned for Java EE 9. Againn lots of speculation here, as everything is in early planning stages. One thing that I found interesting is the addition of a standard Java EE API for NoSQL databases, at this moment it is not clear if it will be a completely new API or an enhancement to JPA.

The next session I attended was on JSON-B, the new Java API for JSON Binding. This is a new API scheduled to be included with Java EE 7, this new API will populate Java objects from JSON strings, and vice-versa.

I then skipped the JCP party to attend the "Java EE for the Cloud" Birds of a feather (BOF) session. This BOF session was surprisingly well attended, it started at 7:00 pm, usually night sessions are not that well attended, they compete with parties and with tired, jet-lagged attendees, looks like many people, like myself, care deeply about the future of Java EE. There were very good questions in this session, for example, there is a new security API proposed for Java EE 7, one of the attendees asked about integrating applications using the existing security APIs with the new proposed Java EE 8 API. In this session the comment was made that, although speculation at this time, it is possible that Java EE 9 will do away with the concept of application servers, in favor of Java 9 modules.

There are lots of sessions on Java EE 8 and Java EE 9 during the conference, I will do my best to attend as many as I can, to try and pick the brains of the individuals working on the new specifications for these future Java EE versions.


The Coolest things I"ve seen at JavaOne 2016 so far

Day one of JavaOne 2016 is in the books. Day 1 is typically JavaOne's NetBeans Day, and this year was no exception. Yesterday I had the opportunity to attend several sessions showcasing NetBeans capabilities, I saw features present in the current version of NetBeans, some features are available in the upcoming NetBeans 8.2, others, Java 9 features specifically, will be available in a future version of NetBeans, but you can start experimenting with them today by downloading the NetBeans Java 9 build.

In no particular order, here are some of the coolest things I saw yesterday on day one of JavaOne 2016.

  1. Adding new refactoring capabilities to NetBeans on the fly.
    Michael Nascimento Santos (@mr__m) demoed how to add refactoring capabilities to NetBeans on the fly with Project Jackpot. The specific example he showed was to add the capability for NetBeans to provide warnings when using Joda-Time, and suggest that the code use Java 8's Date/Time API instead. Java 8, for those that don't know, introduced an improved Date / Time API which is much nicer than was what available with Java in earlier versions. Before Java 8, your best bet when working with dates was to use the Joda-Time library. You can see a video of Michael's demo here.
  2. Create complete Java EE applications with JPA Modeler.
    Gaurav Gupta (@jGauravGupta) demonstrated a very cool NetBeans plugin called JPA Modeler. JPA Modeler can generate database tables, JPA artifacts (entities, DAO's etc), and even complete Java EE applications just from a database model. The tool works like those graphical applications that DBA's use to create the database (i.e things like ERWin), but goes beyond the capabilities of these tools by generating a scaffold of your Java EE application. Gaurav is JPA Modelers project lead.
  3. NetBeans JShell Integration
    JShell is a new upcoming feature of Java 9, it allows to write "low ceremony Java", which means, to develop a "Hello World" program, you would just have to type System.out.println("Hello, World"), instead of having to declare a class, create a main() method, etc. The NetBeans Java 9 build includes built-in support for JShell, you can open a JShell window from NetBeans, experiment with your Java code, then automatically create a Java class with your JShell code snippets. Geertjan Wielenga (@GeertjanW) demoed all this, it was jaw droppingly cool. You can read a blog post explaining NetBeans JShell integration in Geertjan's blog.


JavaOne 2015 Java EE Hands-on Lab

Earlier today I delivered my JavaOne Java EE Hands-On Lab session with Reza Rahman and Bob Larsen. The session was completely packed and well received. We covered topics such as JavaServer Faces (JSF), Contexts and Dependency Injection (CDI), the Java Persistence API, and Enterprise JavaBeans (EJB). 

I delivered the same talk last year, it was so popular that this year we're scheduled to deliver it twice, both sessions are completely packed. I'll be delivering the same talk tomorrow morning at 8:30 am in the Hilton Franciscan B/C/D room.

The session is actually based on a week-long class I taught for one of my clients. The JavaOne version is compressed to fit in a 2 hour session. I'll be happy to teach the full course for anyone that would like to get more in-depth training, contact me at dheffelfinger at ensode dot com for details, my Java EE with GlassFish and Java EE with NetBeans books also contain additional material.

Some of the students requested a copy of the materials, and I'm happy to oblige. Click here to download a zip file containing all the materials, including the slides, exercise manual, source code for the demo and exercise solutions.



Scrollbars in Linux Mint Cinnamon

I like Linux Mint, and I have been using it as my primary Linux distribution for a couple of years now, but one thing that bugged me was the lack of scrollbars for some applications.

I had Googled around, and found some solutions, unfortunately while the solutions worked for most applications, some of my most frequently used applications like the terminal, Nemo (the file manager), and gedit were still lacking scrollbars.

I finally found a solution, first, I had to install the scrollbar-overlay package:

sudo apt-get install overlay-scrollbar

Then, from a terminal window, run the following command:

gsettings set com.canonical.desktop.interface scrollbar-mode normal

I finally have a scrollbar in all of my applications. That really was harder to figure out than it should have been.


JavaOne 2014 Trip Report

I just came back from my annual trip to JavaOne. As usual, the conference was great. This year I had two talks, I participated in a panel at NetBeans day on Sunday right after the Technical Keynote. The title of the session was "Get Productive with Free Java Tools". I had the pleasure of presenting with Tony Epple (@monacotony), who was moderating the panel and gave a quick demo on DukeScript, Sven Reimers (@SvenNB), who showed how to integrate the NetBeans IDE with JavaFX's SceneBuilder, Michelle Chamberlin, who explained the cool things she is doing at Boeing with the NetBeans platform, and Bernd Ruehlicke, who presented how the NetBeans platform is being used in the oil industry.

My other session was a Java EE Hands-On Lab I co-presented with Mark Heckler (@MkHeck). Many thanks to Josh Juneau (@javajuneau), Sven Reimers (@SvenNB) and Bob Larsen, who helped us proctor the lab. The session was packed to the brim, there was a waiting list and many couldn't make it inside.

Feedback for the Hands-On Lab was great, attendees were stopping me in the hallway to tell me how much they enjoyed it, made my day. If you were one of those who couldn't make it in, or if you couldn't make it to the conference, all the materials for the lab can be found at http://ensode.net/downloads/JavaEE_Hands_On_Lab.zip.

In addition to my own sessions, I attended several sessions by some of the other great speakers. Sunday morning I attended the GlassFish community panel, with John Clingan (@jclingan), Cameron Purdy (@cpurdy) and Anil Gaur (@annilgaur), moderated by Reza Rahman (@reza_rahman), in this session, the panelists reiterated Oracle's commitment to GlassFish.



During the GlassFish Adoption session Mohamed Taman (@_tamanm) talked about a large scale deployment in Egypt, in which he used GlassFish on a UN project. His company won the contract, and  by the time they started to work on it most of the work was already in place, readily impressing his client. Mohammed also briefly talked about this project during the community keynote. Martin Mares (@MartinJMares) also talked during this session, showing some cool things he is doing with the GlassFish command line administration tool, asadmin.

I then attended the technical keynote, which included speakers from IBM and Oracle. The keynote was running behind schedule, I had to leave early since I had a session right after, as I'm sure you've heard by now, Brian Goetz (@BrianGoetz) was kicked out of the stage towards the end. I missed when it happened live, but I plan to watch the recording.

Later on Sunday I attended a session on using NetBeans for teaching, with Ken Fogel (@omniprof), Johannes Weigend (@JohannesWeigend), Paul Anderson (@Paul_ASGTeach), Gail Anderson (@gail_asgteach), Zoran Severac (@neuroph) and Andreas Stefik (@AndreasStefik). In addition to my daytime job as a Java EE software developer, I sometimes teach short courses on Java EE using NetBeans, I picked some good tips from this session that I'm sure to use in future courses.

John Ament (@JohnAment) gave a talk on Monday morning about building RESTful web services outside an application server.

On Monday, there were many sessions about the future of Java EE, Linda DeMichiel  had a very interesting presentation about the future of the platform as a whole. Pavel Bucek (@pavel_bucek) had a session about the future of the Java API for WebSocket. Martin Grebac (@mgrebac) had a session on the JSONB specification that is slated to be included in Java EE 8.

Geertjan Wielenga (@GeertjanW) and JB Brock (@peppertech) had a great
session on Monday about Coding for Desktop and Mobile with HTML5 and Java EE 7. In
this session they showed the NetBeans / Chrome integration, in which
changes to the markup in NetBeans result in an instant refresh on the
browser, greatly speeding up web application development, very

On Monday night I attended a couple of GlassFish Birds-of-a-Feather
(BOF) sessions. The first GlassFish BOF was the GlassFish Community BOF
and was led by John Clingan (@jclingan), I had the pleasure of meeting
Manfred Riem @mriem, JSF and MVC co-spec lead during this BOF. The
second GlassFish BOF was about contributing to GlassFish, it was led by
Reza Rahman (@reza_rahman), GlassFish and Java EE evengelist at Oracle,
and Steve Millidge. Steve is the CEO
of C2B2 consulting, a consulting firm in the UK, and is
also the man behind Payara, a new supported distribution of GlassFish,
if you are using GlassFish for your Java EE project, you should check Payara out.

I also attended a JSF BOF on Monday night, in which
Kito Mann (@kito99) and another JSF expert group member explained their
ideas for future features in JSF.

On Tuesday, Arun Gupta (@arungupta) had an interesting talk about
lessons learned in real-life Java EE 7 projects. In this session he
described several Java EE 7 already in production, including Mohamed
Taman's project that was featured in the technical keynote on Sunday.

Also on Tuesday, David Delabassee (@delabassee) had a very interesting talk about
implementing home automation with JavaEE. He was actually controlling
the lights in his home office in Belgium live from the session, which
was being held in San Francisco, very cool stuff.

Tuesday night there was a BOF on meeting with the Java EE specification leads with Bill Shannon, Linda DeMichiel, Ed Burns (@edburns), Manfried Riem (@mriem), Pavel Bucek (@pavel_bucek), and all other Java EE specification leads. It is always an honor to be in the same room with those to work so hard to bring us the latest Java EE specs.

Josh Juneau (@javajuneau) had a session Wednesday afternoon about Concurrency Utilities for Java EE, a new API that was introduced in Java EE 7.

On Thursday morning I attended the community keynote, it started with Michael Greene from Intel, we saw some of the stuff that Intel is doing with Java on the server side, also, there was an announcement about Intel joining the OpenJDK project. During the community keynote, there was a lot of very interesting coverage about Java powered robots, including automated cars from Perrone Robotics, a company based in Charlottesville, Virginia, not too far from my neck of the woods. There were several community members on stage at one point or another. The community keynote wrapped up with no other than James Gosling, the father of the Java language, talking about how Java has come full circle, it started as an "Internet of Things" language, and is currently used more and more in that realm.

An annual tradition during JavaOne keynotes is that at one point or another, they start throwing t-shirts at the audience. This year there was a twist, they were using a rubber catapult contraption to be able to throw t-shirts to members of the audience that are sitting farther back (side note, Sven Reimers, which was sitting two seats away from me, got hit in the face with one of these t-shirts thrown using the contraption, Sven, if you are reading this, I hope you are ok, but that was very funny). Every year I try very hard to catch one of these t-shirts, to no avail, this year, I finally was able to catch one.

On Thursday right after the community keynote there was a very
interesting Java EE 8 community panel, with representatives from all
major Java EE application servers, including [dude's name] from IBM,
Mark Little [twitter] from Red Hat, David Blevins (@dblevins) from Tomee
[spelling], Cameron Purdy representing GlassFish, John Clingan
(@jclingan) representing the Avatar project. And Adam Bien representing
himself as a member of the Java EE community.

Bruno Borges (@brunoborges) had an interesting session Thursday afternoon on implementing JavaFX clients for Java EE server side code.

Also on Thursday, Adam Bien (@abien) had a cool session about using Nashorn, the JavaScript implementation included in the Java Development Kit (JDK) 8, in Java EE applications. Adam is a great speaker, make sure you check his AirHacks online seminars.

I tend to focus on Java EE sessions when I go to JavaOne, but this year I went to a couple of sessions covering other very cool stuff. Tony Epple (@monacotony) and Jaroslav Tulach (@JaroslavTulach) had a very funny and informative session about DukeScript, DukeScript applications are plain Java applications that internally use HTML5 technologies and JavaScript for rendering.

Baruch Sadogursky  and Yoav Landman , another great comedic duo, had a great session on Groovy puzzlers.

Venkat Subramaniam (@venkat_s) delivered a fast paced, humorous and interesting talk on Groovy closures, this was late in the day on Thursday, a great way to end the conference.

A major part of the conference is the vendor's booths. This year I dropped by the Tomitribe booth, Tomitribe provides support for the Apache TomEE application server. I also visited the CodeName One booth, these guys make a product that allows you to develop applications in Java for both Android and Mac OS. I also dropped by the IDR solutions booth, this company makes a product that converts PDF documents to HTML5, and the Payara booth, who provides technical support for GlassFish.

Wednesday afternoon I had a book signing at the JavaOne bookstore, my first time signing books at JavaOne, great experience.

In addition to sessions, booths and book signings, JavaOne always has plenty of social activities. This year I attended the NetBeans party on Saturday night, the Java EE community appreciation event on Sunday night, and the JCP party on Monday night. I also attended the Oracle appreciation event, this year they had none other than Aerosmith playing at the event.

As always, JavaOne was awesome, great sessions, great social activities and above all the opportunity to rub shoulders with the greatest minds in the Java community. Every year I meet new great people from all over the world, and even though I don't see them often, when I run to them at the conference it is always as if I'm meeting with old friends.

Next year marks the 20th anniversary of the Java language, I'm sure JavaOne 2015 will be out of this world, I can't wait.


5 Perks You can offer to attract good Software Developers

Software developers are in high demand nowadays. We get contacted on a daily basis by companies requesting we go work for them. We frequently get emails with the words "Great Opportunity!" and "Urgent Requirement". The thing is, not many of the projects we get contacted for offer compelling reasons for us to make the change. I decided to make a list of things that would make us as software developers consider the possibility of moving on to another project.

1. Working on a brand new project

Most of the projects out there are maintenance of an existing application, brand new projects built from the ground up are few and far in between. If you have a brand new project, then you have a leg up over all the other companies looking to hire software development talent.

2. Quiet working spaces

Software development requires concentration, this concentration is hard to obtain in the modern cubicle farm, with all the interruptions around (conversations, phones ringing etc). Offer your developers quiet working spaces and you have a perk that most employers around can't offer. Ideally, give each developer their own private office, now you really have a perk that puts you head and shoulders above the competition. If you can offer private offices, at least offer cubicles with doors, which provide a bit more privacy than the usual open cubicles.

3. The ability to work remotely

Nowadays high speed internet is so common, that there really is no reason for most people to actually drive to an office. A lot of companies want to see "butts in chairs", this is really not necessary, you should know if the work is getting done, your development team does not have to physically be at your location. This is one very rare perk, offering this will certainly make your company an attractive place to work for software developers. This also has the side effect of increasing the available talent pool, since members of the development team does not have to live in the same geographical area as your company.

4. Allow the development team to use their own equipment

To this day, many companies are shy about allowing non-company laptops into their network. The development team has to use company approved hardware. Many software developers would prefer to work using their own laptops, it shouldn't be a big deal to allow them to do so. As a bonus, when working with a programming language that is platform independent, such as Java, it doesn't matter if the developer is using a Mac, Windows or Linux, therefore developers can work with their preferred platform, as opposed to being tied to whatever the company standard is.

5. Keep meetings to a minimum

In my experience, in most cases, most people attending a meeting have no real business being there. They could be doing productive work instead. Meetings interrupt the workflow of software developers and in most cases are a massive waste of time. I'd recommend not more than a 1 hour meeting a week. If you need daily status reports, an email works better than a daily meeting, that way the developers can do it at their leisure, not at a set time, and they don't have to sit through and listen to the status of all the other team members, which more than likely has no impact whatsoever in whatever they may be working on.


Things I would tell recruiters if I wasn't afraid to sound arrogant

I am fortunate enough to work in a field for which there is a lot of demand out there. I get multiple emails every day from companies asking for help with their server side Java projects. Java developers such as myself

1. Don't call your position "an opportunity"
Like I mentined in the intro, I get tons of "opportunities" every day via email or LinkedIn messages. Java projects are a dime a dozen, chances are your project is not a "great opportunity" for me. You know and I know that Java developers are hard to find, if anything, me agreeing to work on your project is an opportunity for you, and not for me.

2. Don't say you have an "urgent requirement"
You may urgently need a Java developer, and I'm here drowning in emails from recruiters that also need Java developers. It may be urgent for you to fill that position, but it is not urgent for me to accept it. While we are on the topic, don't say the requirement is urgent if you are not willing to be flexible. One perk that would certainly catch my attention would be the ability to work remotely, but very few customers are open to the possiblity. If your requirement is so urgent, shouldn't you be a bit more flexible? Oh, and by the way, no, I am not willing to relocate just so that I can work on a 6 month project.

3. I don't stay on the market too long.
I work as a consultant on a C2C basis, therefore I switch projects every few months. Every time I post my resume on one of the job boards, I get bombarded with calls and emails from recruiters (even more so than when I'm not actively looking).
If you are interested in my services, you have to move fast, chances are that in a week or less I won't be in the market anymore.

4. Don't make me jump through hoops
I've written several books on Java, taught Java classes and been a speaker at Java conferences, as well as having about 18 years of experience. I think my experience speaks for itself. Please don't make me go through several rounds of interviews or take a silly test just so that I can work on your project. Just by talking to one of your developers he or she will be able to tell that I know what I'm talking about.

5. If I accept/am about to accept another project, don't ask me to "wait a few days"
As much as I get contacted by recruiters for several different positions, it is mentally exhausting and draining to talk to several potential clients, send resumes, etc. I just want to get it over with, so as soon as I get an offer, I'm taking it.

Java EE Course Trip Report

I just came back from teaching a Java EE class in San Francisco.

The course lasted two days, and it covered the most commonly used Java EE technologies and API's such as JavaServer Faces (JSF), Contexts and Dependency Injection (CDI), Enterprise JavaBeans (EJB), the Java Persistence API and the Java Message Service(JMS). The course also touched on Bean Validation and the Java API for RESTful Web Services (JAX-RS).

The students were veteran Java developers and architects, ranging from around 5 to 18 years of experience. There were a few students that had use EJB's back in the J2EE era, some that had used earlier versions of JSF (1.x) and some that had been focusing on Spring for their server side Java development.

None of the students had use modern versions of EJB or JSF, they were very impressed on how much easier modern versions of these frameworks are compared to their Java EE counterparts.

Since we had only two days, we only covered the basics of each technology, such as Facelets markup for JSF. For CDI, we covered context (scope) annotations and dependency injection for CDI. We mentioned additional CDI features such as qualifiers, stereotypes and interceptor binding types.

The different Bean Validation annotations were covered, pointing out how simple it is to do validation using just a few simple annotations. As far as EJB's go, I covered the different type of session beans, such as Stateless, Stateful, and Singleton session beans; as well as Message driven beans. For EJB's we went a bit deeper, covering things such as transaction management, interceptors for Aspect Oriented Programming (AOP) and the EJB timer service.

When talking about JPA, the class covered basic JPA annotations such as @Table and @Column, as well as one-to-many, many-to-one, many-to-many and one-to-one entity relationships. We also covered eager vs lazy fetching, and the advantages and disadvantages of each approach. We ended the JPA topic with a discussion of the Java Persistence Query Language (JPQL) and the JPA Criteria API.

I overheard some comments from the students, for example, one mentioned "EJB's are cool", which I completely agree. Another student noted that there isn't anything in Java EE that he cannot accomplish with Spring, which, while it may be true that the end result is the same, fails to take into account that the amount of work to get this end result tends to be a lot less with Java EE.

There were hands-on labs for the students to practice the concepts taught in class. I chose NetBeans as the IDE for the exercises, since it comes bundled out of the box with everything needed to build complete applications, such as a Java EE compliant application server (GlassFish), and a fully functional RDBMS (JavaDB). Not many of the students had previous NetBeans experience, however most of them were able to finish the exercises (which were simple, but complete Java EE applications) in about 30 minutes or so.

While discussing the hands-on labs, I provided some NetBeans tips, such as the ability to generate boilerplate code (Alt-Ins), generate JPA entities from an existing database, and the NetBeans JPQL editor, which provides code completion when developing JPQL queries.

All in all, a great experience. I don't get to teach as often as I'd like, it is a nice change of pace from my day to day job developing real-life Java EE applications.


JavaServer Faces (JSF) in a Hurry

Need to learn JSF in a hurry? I'm here to help!

Assuming you already have some Java experience, as well as some HTML experience, there is nothing to JSF, you can learn the basics in a few minutes. I also assume that you are familiar with packaging and deploying Java code to an application server such as GlassFish, WildFly, JBoss, Weblogic or Websphere, or to a servlet container such as Tomcat or Jetty.

JSF has evolved over the years, this blog post covers the best practices in JSF 2.0 or newer, specifically, Facelets is used to develop the front end (as opposed to JSP) and CDI Named beans are used to develop the server side code (as opposed to managed beans).

Step 1: Develop Java class(es) that will hold information (the Model in the MVC pattern)

Your Java class will be a Plain Old Java Object (POJO), it will consist of private properties public setters and getters.

package com.ensode.jsfinahurry.model;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

public class Person {

    private String firstName;
    private String lastName;
    private Short age;

    public String getFirstName() {
        return firstName;

    public void setFirstName(String firstName) {
        this.firstName = firstName;

    public String getLastName() {
        return lastName;

    public void setLastName(String lastName) {
        this.lastName = lastName;

    public Short getAge() {
        return age;

    public void setAge(Short age) {
        this.age = age;


The @Named annotation designates the class as a CDI managed bean, gives it a name, which by default is the class name with its first character switched to lowercase (“person”, in our case). This annotation allows JSF pages to access our Java class.

The @RequestScoped annotation gives our CDI bean a scope of request. If you have developed web applications in Java before you should be familiar with bean scopes by now.

The following table shows the most commonly used scopes for CDI named beans:

 Annotation Scope
 @RequestScoped Request
 @SessionScoped Session
 @ApplicationScoped Application
 @ConversationScoped Conversation
 @FlowScoped Flow
 @Dependent Dependent pseudo scope

The first three should be self-explanatory, the last two (@ConversationScoped and @FlowScoped) are both meant for the bean to live throughout two or more requests, but not last through the whole session. Since we're in a hurry, I can't explain these in detail, but suffice to say that @FlowScoped was introduced in JSF 2.2 as part of Java EE 7 and is the preferred way to achieve this functionality if you are using JSF 2.2 or newer. @Dependent just means that the bean will be created as needed.

Step 2: Develop a controller class

This is the controller in the Model-View-Controller (MVC) design pattern. As far as plumbing, there is not much to do for controllers, just use the @Named annotation and an appropriate annotation.
package com.ensode.jsfinahurry.controller;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

public class PersonController {
    public String processData(){
        //in a real application, we would process user-input here
        //more than likely saving data to a database
        return "confirmation";

Our JSF pages will invoke the processData() method when the user clicks on a button, via a method binding expression (next section). By convention, the next page to render in the browser will match the return value of the invoked method (processData(), in our case). For our example, we will develop a page named confirmation.xhtml (matching the return value of “confirmation”) that will be rendered after our processData() method is invoked.
Step 3: Develop the pages
Now that we have our Java code in place, we need to develop the user interface. JSF pages are developed using Facelets, a JSF specific view technology. Facelets pages are nothing but standard XHTML pages using some JSF specific name pages.
A page used to allow the user to enter person data (to be stored in our Person class) may look like this:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<html xmlns="http://www.w3.org/1999/xhtml"
        <title>Enter Person Data</title>
        <h3>Enter Person Data</h3>
        <h:form id=”personForm”>
            <h:panelGrid columns="2">
                <h:outputLabel for="firstName" value="First Name"/>
                <h:inputText id="firstName" label="First Name" value="#{person.firstName}"/>
                <h:outputLabel for="lastName" value="Last Name"/>
                <h:inputText id="lastName" label="Last Name" value="#{person.lastName}"/>
                <h:outputLabel for="age" value="Age"/>
                <h:inputText id="age" label="Age" value="#{person.age}"/>
                <h:commandButton value="Submit" action="#{personController.processData()}"/>

If you know even basic HTML, you should have a pretty good idea of how the above Facelets markup works. Before explaining the markup, notice that most JSF specific tags on the page have an id attribute. This attribute is optional, but it is a good idea to set it, for starters, it allows us to link labels to input fields (explained below), but also, when things don't work as expected it is much easier to identify which tag is causing trouble, as most JSF error messages will display the id of the component (if we don't set it, JSF will assign one, that will be meaningless to us).

The <h:head> and <h:body> tags are drop-in replacements for HTML <head> and <body> tags.
<h:form> is equivalent to the HTML <form> tag, notice that for JSF we don't need to specify the method and action attributes (method will always be “post” and the action will always point to the JSF servlet, which is automatically used when developing with JSF).

The <h:panelGrid> component lays out JSF tags on the page, similar to using a table to lay out HTML tags. Its column attribute specifies how many tags will be placed in each column.
<h:outputLabel> renders an HTML <label> tag, its “for” attribute must match the id attribute of the input component the label is meant for.

<h:inputText> is equivalent to an HTML <input> tag with a type of “text”. A nice thing about JSF is that it automatically converts user-entered values to the appropriate type in the corresponding CDI named bean. The value of the value attribute is what is known as a value binding expression, we can recognize these since they are encapsulated in curly braces and preceded by a hash (i.e. #{..}). Value binding expressions are used to automatically populate the corresponding attribute in a CDI named bean with the user-entered value for the corresponding input text. Remember the @Named annotation? “person” inside each value attribute corresponds to the name of our Person bean. The value after the dot corresponds to the corresponding property in the Person bean. For example,  #{person.firstName} corresponds to the firstName property of the Person bean.

<h:panelGroup> is used to group JSF tags together in a single cell. In our case, all we wanted to do was have an empty cell so that our button would vertically align with the rest of the input fields, so we placed an empty <h:panelGroup> tag at the appropriate location in our <h:panelGrid>.

Finally, <h:commandButton> submits our form, its value attribute sets the label for the button, its action attribute indicates which CDI named bean method to execute when the button is clicked (processData(), in our case). This is what is called a method binding expression. The method must be public, return a String and take no arguments. What we implemented here is what is referred to as dynamic navigation, although our simple example always returns the same String, there is nothing stopping us from returning different values depending on some conditions, we can then take the user to different pages depending on these conditions (picture a switch statement or if/then/else, with different return values for different conditions).
If we don't need to do any processing after the user clicks the button and we always will display the same page, we can use static navigation, in which case the value of the action attribute can be hardcoded, like this:

<h:commandButton value=”Submit” action=”somepage”/>

We know that the value is hardcoded and not an expression since it is not surrounded by curly braces preceded by a pound sign (“#{...}”). In this case a page named somepage.xhtml would be rendered on the browser every time the user clicks on the button.
The markup for our confirmation page simply displays the values the user entered on the previous page.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<html xmlns="http://www.w3.org/1999/xhtml"
        <title>Confirmation Page</title>
        <h3>You entered the following data</h3>
        <b>First Name:</b> ${person.firstName}<br/>
        <b>Last Name:</b>${person.lastName}<br/>

The only thing new on this page is the use of curly braces preceded by a dollar sign (“${...}”) to retrieve a named bean's properties. When the page is displayed the value of the corresponding property is displayed on the page.

Our application in action

Once we package our application in a WAR file and deploy it to our application server of choice (I'm using GlassFish), our input page will be rendered. Here is what it would look like after a user entered some data:

Notice that we didn't have to specify any mappings in web.xml (as a matter of fact, web.xml is optional in modern JSF applications). By default, JSF pages are mapped to the /faces prefix.
When the user clicks on the Submit button, the processData() method on our PersonController class is executed, which takes us to the confirmation screen.

What I left out

This post is meant as a quick introduction to JSF, so I obviously did not cover every JSF nook and cranny. There are lots of additional JSF tags that I didn't cover, there are JSF specific equivalents to every HTML input tag.

JSF also has input validation built-in, we can make fields required and also accept only specific formats, for example. For application specific cases, we can develop our own custom validators.

JSF has built-in data conversion, we saw this in action by adding a property of type short and having the user-entered value automatically converted to the appropriate type. JSF also allows us to develop custom data converters.

JSF also has Ajax integration built in, a topic that I obviously didn't cover.
Finally, almost nobody develops “raw” JSF applications, the beauty of JSF is that allows the creation of component libraries. Most JSF applications employ one of these component libraries. Some of the most popular include PrimeFaces, RichFaces and IceFaces.

Where to go from here

After reading this short blog post, you should have a pretty good idea of the basic mechanics of JSF. To learn more about it, I'd be very grateful if you purchased one my books, Java EE 7 Development With GlassFish 4 or Java EE 6 Development With NetBeans, or, if you need personalized training, I can help you with that as well, just head over to my company web site: http://www.ensode.com for my contact information.
Of course, there is a ton of free information on the web as well, now that you know the basics other tutorials out there that assume basic knowledge should make more sense, just use your favorite search engine to find out more.

 The source code for the example shown in this post can be downloaded here.


Java Lingo for Non-Java People

This post is meant for managers, business analysts, recruiters, and anyone else who needs to interact with Java developers but is not a Java developer him/herself.
Just like any other discipline, Java development is full with lingo that may be intimidating to those not in the field.

Java itself is a programming language that is platform independent, which means that Java code can run unmodified on a variety of operating systems such as Windows, Linux/Unix, and Mac OS. Traditionally source code needs to be compiled for each specific platform, this is not the case for Java.

The Java Virtual Machine
But Java is not only a programming language, it is also a platform. Java code runs on the Java Virtual Machine (JVM), which translates Java bytecode (compiled Java code) into native code for each platform. There are several other languages that run in the JVM, such as JRuby, Clojure, Groovy, Ceylon and many others.

Eclipse, NetBeans, IDEA
Java applications are typically developed using an Integrated Development Environment (IDE), the three most popular IDEs are Eclipse, NetBeans and IntelliJ IDEA.

ANT, Maven, Gradle
Java applications also typically use a build tool to help compile, build and deploy applications, the three most popular build tools are ANT, Maven and Gradle.

Java EE, JEE, J2EE
Java is extremely popular for developing enterprise server side applications, these types of applications typically use a web based user interface, with the business logic running on a server. Java Enterprise Edition (Java EE) is a set of Application Programming Interfaces (APIs) used to develop server side applications. Sometimes Java EE is referred to as JEE, however the officially sanctioned name is Java EE and the use of the term JEE is discouraged by Oracle, the company behind the Java platform (Oracle bought Sun Microsystems, the original company behind Java, back in 2010). Java EE was formerly known as J2EE, the J2EE term was so popular that it is still commonly used to refer to Java EE.

The Spring framework is an alternate set of APIs used to develop server side applications. In general, server side Java developers belong to either the Java EE or Spring camps, rare is the developer that is a fan of both.

GlassFish, Weblogic, Websphere, JBoss, Tomcat, etc
Server side Java applications are deployed to an application server. Application servers provide functionality that is common to all enterprise applications so that application developers don't have to concern themselves with implementing this functionality. For example, application servers take care of transaction management, security and scalability. Some examples of application servers include GlassFish, JBoss, WildFly, Weblogic and Websphere. Tomcat can be thought of as an application server as well, however strictly speaking, it is a servlet container, that is, it provides less functionality out of the box than full fledged application servers. Java applications written using Spring typically don't require a full fledged application server and can be deployed to Tomcat. Another popular servlet container is Jetty.

JSF, Struts, GWT, Etc
There are several Java web frameworks that are used to ease and accelerate the development of web based applications. JavaServer Faces (JSF) is the standard Java EE framework for web development. There are several JSF component libraries that run on top of JSF, these libraries make it easy to develop nice looking JSF based web applications. Some examples of these libraries include PrimeFaces, RichFaces and IceFaces. In addition to JSF, there are several other Java web frameworks such as Struts (considered by many to be a legacy framework), the Google Web Toolkit (GWT), Struts Web MVC and Wicket.

On the server side, Enterprise JavaBeans (EJBs) provide transactions, security and scalability out of the box. This frees Java developer from having to implement this functionality and allows them to focus on implementing the business logic.

JPA, Hibernate, MyBatis
There are Java APIs (Application Programming Interfaces) that help developers write code to interact with a database, the Java Persistence API (JPA) is the standard Java EE API used for this purpose. Hibernate and MyBatis (formerly known as iBatis) are two other popular libraries used for this purpose.

So there you have it, my friend, after reading this post you'll have some idea of what the heck those Java guys are talking about or what it is that is needed for that Java developer position your company is hiring for.

Anything I missed? Leave a comment.


So you want to become an independent consultant?

I have been an independent consultant for almost 7 years. Last month I had the opportunity to speak at the JavaOne conference, I identified myself as an independent consultant, after my talks a few attendees approached me to ask how to go about becoming one.

The other day a former coworker found my LinkedIn profile, saw that I'm independent now and gave me a call asking for advice and guidance on going on his own.

Since there seems to be a lot of interest in finding out how to strike it out on your own, I'll write down about my experiences here, then in the future direct people to this blog post.

The first thing I'd like to clarify is that I live in an area where most software development work is contract work anyway. Another thing that I'd like to point out is that by the time I decided to go out on my own I was already a published author, that fact helped me market my services and obtain work fairly easily. Your mileage, as they say, may vary.

When doing contract work, there are three ways to go about it.

W2, 1099 or C2C?

When hired as a W2, you become a temporary employee of the company hiring you. The client (your temporary employer) takes care of your tax deductions. There are also 1099 contracts, in which the company hires you as an individual, but you are not their employee, you are responsible for deducting your own taxes. The third way to do it is a Corp to Corp contract, commonly abbreviated as C2C. When doing C2C contracts, you need to incorporate a company, in this case the clients hires your company, not you directly.

Before I incorporated Ensode Technology, LLC, I was doing a lot of W2 contracts, since like I mentioned before the majority of software development work in my area is contract work . W2 contracts usually lasts from 6 months to a year, in rare occasions it can go beyond that. Since I had no job security anyway I figured that I may as well go all the way, start my own company and incorporate.

How do I incorporate my own company?

Incorporating a company is very easy. First come up with a name, google it to make sure it is not taken (by the way Ensode stands for Enterprise Software Development). I incorporated Ensode Technology online and didn't even had to get up from my seat, if I remember correctly it cost me about $100 USD.

Getting a Business Bank Account

You need to get a business bank account primarily so that you can get paid. Your clients will be writing checks to your company, not to you personally. Any bank will be more than happy to help you open an account with them.

Getting Insurance

After incorporating, the next step was to get insurance, a lot of clients won't do business with you unless you are insured. I have liability insurance covering up to $1,000,000, it costs me about $500 a year.

Taking care of tax deductions

Lastly, I hired a payroll service to take care of my tax deductions, that sets me back around $85 USD a month or so.

Once you have incorporated your company, gotten liability insurance and hired a payroll service (this third step is optional, but I highly recommend it), you are ready to strike it out on your own, so the next question get asked a lot is:

How do you get projects?

When your company has only one employee, getting contracts is not much different from the way most other people find regular jobs. You post your resume on a job board, and wait for companies to contact you, once you start talking about a potential job, you should let them know that you are only looking for C2C contracts.

So there you have it, as you can see striking it out on your own is not really that hard. Good luck in your new venture.


« May 2024

© David R. Heffelfinger