adam bien's blog

Migration from @Stateless (BCE) to Quarkus 📎

A typical BCE Jakarta EE application comprises a JAX-RS resource:

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
    
@Path("ping")
public class MessageResource {

    @Inject
    MessageFetcher messageFetcher;

    @GET
    public String ping() {
        return "hello, " + this.messageFetcher.getMessage();
    }

}
and a corresponding implementation in the boundary package:

package com.airhacks.ping.boundary;
import com.airhacks.ping.control.MessageConfigurator;
import javax.ejb.Stateless;
import javax.inject.Inject;

@Stateless
public class MessageFetcher {

    @Inject
    MessageConfigurator configurator;

    public String getMessage() {
        return this.configurator.message();
    }

}

The boundary acts as a facade and usually coordinates multiple controls:


package com.airhacks.ping.control;

import javax.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;

public class MessageConfigurator {

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

    public String message() {
        return this.message + " generated at: " + System.currentTimeMillis();
    }
}    

To run the code on quarkus you will have to replace @Stateless with @Transactional and @RequestScoped, or a stereotype which combines both:


@Stereotype
@Transactional
@RequestScoped
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Boundary {}    

Now the MessageFetcher looks like:


@Boundary
public class MessageFetcher {    }    

All controls have to annotated to be injectable on quarkus. A @Dependent (default) scope could be used for that purpose, or the following stereotype:


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Stereotype;

@Stereotype
@Dependent
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Control {}

The MessageConfigurator control has to be annotated with the @Control stereotype and looks like:


@Control    
public class MessageConfigurator { }

Both stereotype are used in the Web Push gateway: gatelink.