Jakarta EE 11 and Beyond
[Your name]
[Your title]
[Your contact information]
Jakarta EE
VMware, Alibaba, London Java Community, OmniFish, SouJava, Apache
The Importance of Jakarta EE
2024 Jakarta EE Developer Survey: https://outreach.eclipse.foundation/jakarta-ee-developer-survey-2024
Jakarta EE Evolution
JPE
J2EE 1.2
Servlet, JSP, EJB, JMS
J2EE 1.3
CMP, JCA
J2EE 1.4
JAX-WS
Java EE 5
EJB 3, JPA, JSF, JAXB, JAX-WS
Java EE 7
WebSocket, JSON, Concurrency, Batch, pruning
Java EE 8
HTTP/2, SSE, Security, pruning
Java EE 6
Profiles, CDI, JAX-RS, Bean Validation
Jakarta EE 8
Open-source governance
Jakarta EE 9.x
Namespace
transition
Jakarta EE 10
New features, updates
Jakarta EE 11
New APIs, features, updates
A Lively Ecosystem
Ambassadors’ Jakarta EE 11 Contribution Guide
Jakarta EE 10 in Context
Made it! On the way Gap
Jakarta EE 11 in Context
Made it! On the way Gap
Jakarta EE 11 Themes
Jakarta EE 11 at a Glance
Platform
Web Profile
Core Profile
Jakarta Persistence
Embeddable Records
@Embeddable
public record Address (String street, String city,
String state, String zipCode) {
}
@Entity public class Person {
@Id private Long id;
private String firstName;
private String lastName;
@Embedded private Address address;
...
}
EntityManager via @Inject
<persistence>
<persistence-unit name="MyPU">
<jta-data-source>java:app/jdbc/MyDS</jta-data-source>
<scope>jakarta.transaction.TransactionScoped</scope>
@ApplicationScoped @Transactional
public class BookService {
@Inject EntityManager EntityManager;
Jakarta Concurrency
Managed Virtual Threads
@ManagedExecutorDefinition(
name = "java:app/concurrent/MyExecutorService",
maxAsync = 5,
virtual = true
)
@Schedule in CDI Beans
@ApplicationScoped
public class UploadDirectoryScanner {
@Asynchronous(runAt = {
@Schedule(cron = "*/15 * * * * *")})
public CompletableFuture<Integer> processFiles(int mininumSize) {
...
if (normal) {
return null; // Continue schedule
}
return Asynchronous.Result.complete(reason); // Stop schedule
}
}
Jakarta Security
In-memory Identity Store
@InMemoryIdentityStoreDefinition({
@Credentials(callerName = "peter", password = "secret1",
groups = { "foo", "bar" }),
@Credentials(callerName = "john", password = “secret2",
groups = { "foo", "kaz" })
})
Jakarta Messaging
@MessageListener Example
@ApplicationScoped
@MaxConcurrency(10)
public class HandlingEventRegistrationAttemptConsumer {
@MessageListener(
destinationLookup="jms/HandlingEventRegistrationAttemptQueue",
selector="source = 'mobile'",
batchSize=10, orderBy=TIMESTAMP,
retry=5, retryDelay=7000, deadLetterQueue="jms/DeadLetterQueue")
public void onEventRegistrationAttempt(
HandlingEventRegistrationAttempt... attempts) {
...
}
}
Bootstrap API for Jakarta Messaging
JmsContainer container = JmsContainerFactory.newInstance();
...
JMSContext jmsContext = container.getJmsContext();
Destination handlingEventQueue = container.getDestination(
“jms/HandlingEventRegistrationAttemptQueue” true);
...
jmsContext.createProducer()
.setDisableMessageID(true)
.setDisableMessageTimestamp(true)
.setStringProperty("source", source)
.send(handlingEventQueue, attempt);
...
container.close();
Jakarta Data
Jakarta Data Example
@Entity public class Product {
@Id private long id;
@Column @NotBlank private String name;
@Column @PositiveOrZero private float price;
@Repository public interface Products extends CrudRepository<Product, Long> {
@Asynchronous @OrderBy("price")
CompletableFuture<List<Product>> findByNameContains(String searchFor);
@Query(
"UPDATE Product o SET o.price = o.price - (?2 * o.price) WHERE o.id = ?1")
boolean discount(long productId, float discountRate);
}
Jakarta MVC
Jakarta MVC Example
@Controller
@Path("/")
@View("my-index.xhtml")
public class Bookstore {
@Inject private Models model;
@Inject private BookService service;
...
@GET
public void index() {
...
model.put(“books”, books);
}
}
Jakarta NoSQL
Jakarta NoSQL Example
@Entity public class Order {
@Id private long id;
@Column @NotBlank private String description;
@Column @NotEmpty private List<OrderLine> orderLines;
@Column @NotNull private Customer customer;
@Column @NotNull private Address address;
template.insert(order);
...
List<Order> results = template.select(Order.class)
.where("description").like("^Pinball").result();
logger.info("Found orders for pinball: " + results.size());
Jakarta Configuration
Jakarta Configuration Examples
@Inject
@ConfigProperty(name = “admin.group”, defaultValue=“admin”)
private String adminGroup;
persistence.provider=org.hibernate.ejb.HibernatePersistence
persistence.datasource=java:app/jdbc/CargoTrackerDatabase
persistence.schema.generation.database.action=create
<data-source>
<name>java:app/jdbc/CargoTrackerDatabase</name>
<class-name>org.apache.derby.jdbc.EmbeddedDriver</class-name>
<url>jdbc:derby:${temp.dir}/cargo-tracker-database</url>
</data-source>
Other Changes
Validating Records
public record Car(
@NotBlank String manufacturer,
@NotNull @Size(min = 2, max = 14) String licensePlate,
@Min(2) int seatCount) {
}
Job Definition API Example
Job job = new JobBuilder(jobName).property("jobk1", "J")
.listener("jobListener1", new String[]{"jobListenerk1",
"#{jobParameters['jobListenerPropVal']}"},
.step(new StepBuilder(stepName)
.properties(new String[]{"stepk1", "S"}, new String[]{"stepk2", "S"})
.batchlet(batchlet1Name, new String[]{"batchletk1", "B"},
new String[]{"batchletk2", "B"})
.listener("stepListener1", stepListenerProps)
.stopOn("STOP").restartFrom(stepName).exitStatus()
.endOn("END").exitStatus("new status for end")
.failOn("FAIL").exitStatus()
.nextOn("*").to(step2Name)
.build())
...
.build();
Beyond Specification Work
Ways of Contributing
Summary
Resources