First official JSF 2.3 contribution from zeef.com

27 January 2015

A while back we joined the JSF 2.3 EG as zeef.com. While we had contributed as individuals before (mostly via code suggestions and snippets in JIRA issues) we are proud that today our first more direct contribution was committed to Mojarra for the ongoing JSF 2.3 effort.

Co-spec lead Manfred Riem tweeted about this earlier today:

The commit in question can be seen in our GitHub mirror. To summarize the change; before it was only possible to inject the application map as follows:

@Inject
@ApplicationMap
Map applicationMap;

As can be seen, the map is missing its generic parameters. This is of course far from ideal. With the latest patch, this map can now be injected as it should be:

@Inject
@ApplicationMap
Map<String, Object> applicationMap;

Injection into a raw map is still supported, but for most cases the generic variant should be preferred.

It’s a fairly small change, but hopefully many more of such changes will follow soon ;)



Arjan Tijms

CDI based @Asynchronous alternative

19 January 2015

Arguably one of the most convenient things in EJB after declarative transactions is the @Asynchronous annotation. Applying this annotation to a method will cause it to be executed asynchronously when called (the caller does not have to wait for the method to finish executing).

The downside of this annotation is that it’s only applicable to EJB beans. While EJB beans these days are lightweight and nothing to avoid in general, the fact is that in Java EE 6 and especially Java EE 7 other managed beans, specifically CDI ones, play an increasingly important role. These beans unfortunately can not directly take advantage of the platform provided @Asynchronous.

Building such support ourselves in Java EE 7 however is not that difficult. Thanks to the Java 8, and the Interceptors and Concurrency specs it’s actually quite simple, but with a small caveat (see below):

We’ll start with defining the annotation itself:

@InterceptorBinding
@Target({METHOD})
@Retention(RUNTIME)
@Inherited
public @interface Asynchronous {}

Next we need a helper class that effectively unwraps the dummy Future instance (of type AsyncResult, as provided by the EJB spec) that an asynchronous method returns. Such a wrapper class is needed in Java, since you otherwise can’t call a method that returns say String and assign it to Future<String>. This is not specific to this CDI implementation, but is exactly how EJB’s @Asynchronous works.

public class FutureDelegator implements Future<Object> {
 
    private final Future<?> future;
 
    public FutureDelegator(Future<?> future) {
        this.future = future;
    }
 
    @Override
    public Object get() throws InterruptedException, ExecutionException {
        AsyncResult<?> asyncResult = (AsyncResult<?>) future.get();
        if (asyncResult == null) {
            return null;
        }
 
        return asyncResult.get(); 
    }
 
    @Override
    public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        AsyncResult<?> asyncResult = (AsyncResult<?>) future.get(timeout, unit);
        if (asyncResult == null) {
            return null;
        }
 
        return asyncResult.get(); 
    }
 
    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return future.cancel(mayInterruptIfRunning);
    }
 
    @Override
    public boolean isCancelled() {
        return future.isCancelled();
    }
    @Override
    public boolean isDone() {
        return future.isDone();
    }
}

With those 2 classes in place the actual interceptor can be coded as follows:

@Interceptor
@Asynchronous
@Priority(PLATFORM_BEFORE)
public class AsynchronousInterceptor implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @Resource
    private ManagedExecutorService managedExecutorService;
 
    @AroundInvoke
    public Object submitAsync(InvocationContext ctx) throws Exception {
        return new FutureDelegator(managedExecutorService.submit( ()-> {
return ctx.proceed(); } ));
    }
}

There are a few things to take into account here. The first is the priority of the interceptor. I put it on PLATFORM_BEFORE, which is the absolute lowest level, meaning the interceptor will likely hit before any other interceptor. If this interceptor would ship with a library it’s more correct to use the lowest range reserved for libraries: LIBRARY_BEFORE.

For the actual parallel execution, the call to ctx.proceed() is scheduled on a thread pool using the Java EE Concurrency provided executor service. While this service was only recently introduced in Java EE 7, it in fact originated from a very old spec draft that was dragged into modern times. Unfortunately that spec felt it needed to use the somewhat archaic @Resource annotation for injection instead of the more modern @Inject. So that’s why we use that former one here and not the latter.

A caveat is that the interceptor as given does not work on the current released versions of Weld, but in fact does work on the not yet released SNAPSHOT version. The issue is explained by Jozef on the CDI-dev mailing list.

As a temporary workaround a thread local guard can be used on Weld as follows:

@Interceptor
@Asynchronous
@Priority(PLATFORM_BEFORE)
public class AsynchronousInterceptor implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @Resource
    private ManagedExecutorService managedExecutorService;
 
    private static final ThreadLocal<Boolean> asyncInvocation = new ThreadLocal<Boolean>();
 
    @AroundInvoke
    public synchronized Object submitAsync(InvocationContext ctx) throws Exception {
 
        if (TRUE.equals(asyncInvocation.get())) {
            return ctx.proceed();
        }
 
        return new FutureDelegator(managedExecutorService.submit( ()-> { 
            try {
                asyncInvocation.set(TRUE);
                return ctx.proceed();
            } finally {
                 asyncInvocation.remove();
            }
        }));
    }
}

Future work

The interceptor shown here is just a bare bones copy of the EJB version, but lacks the setup of a request scope. Going further however we can add additional features, like using a completable future, optionally named thread pools, etc.

Arjan Tijms

Follow JSF 2.3 development via GitHub mirror

17 January 2015

Currently development for JSF 2.3 is well underway in the trunk of the Mojarra project.

The Mojarra project still uses SVN, and only has the default web interface up and running. Specifically this means it’s not entirely easy to browse through the commits and see diffs, as this default web interface only offers a very bare bones browsing of the repository.

While there are of course web tools for SVN that show commits and diffs etc, simply importing the SVN repository into GitHub proved to be the easiest solution. So therefor we made a mirror available on GitHub:

github.com/javaeekickoff/mojarra

This mirror is automatically updated every half an hour, so it should never be that far behind the SVN root repository. GitHub provides a number of extra features, such as feeds in atom format. Using that we can easily create widgets such as the one below that shows a near real-time overview of the 3 latest commits:


In addition to this mirror we’ve also published a fork of it, in which we made a few small changes that allows the Mojarra project to be used from Eclipse. This fork is at:

github.com/omnifaces/mojarra

This fork will function as OmniFaces’ feature branch for code that we hope will be integrated into Mojarra and thus JSF 2.3 (which is of course subject to approval by the JSF spec leads and the other EG members).

For completeness, once checked-out, Mojarra can be build using the following steps:

Assuming SOURCE_HOME is the directory containing the source code:

  1. Copy build.properties.glassfish to build.properties
  2. Edit build.properties and set jsf.build.home to SOURCE_HOME
  3. Make sure JAVA_HOME is set and points to a JDK8 install
    e.g. on Ubuntu put JAVA_HOME=/opt/jdk8 in /etc/environment

  4. From SOURCE_HOME run (on the commandline) ant main clean main

The jsf-api.jar will be in SOURCE_HOME/jsf-api/build/lib and jsf-impl.jar will be in SOURCE_HOME/jsf-ri/build/lib.

When making changes from within Eclipse (use the OmniFaces fork for that):

  1. Make changes as needed in .java files, but note that the Eclipse compiled result in SOURCE_HOME/bin must be ignored
  2. From SOURCE_HOME run (on the command line) ant clean main

The jsf-api.jar will again be in SOURCE_HOME/jsf-api/build/lib and jsf-impl.jar will be in SOURCE_HOME/jsf-ri/build/lib.

Do note that the initial build command is ant main clean main, but all following builds happen via the command ant clean main. This is due to a circular dependency, that will likely be removed in the (near) feature if/when the entire project becomes a Maven project. Also note that when that happens, the Eclipse specific changes in the OmniFaces fork of Mojarra will not be needed anymore either.

Arjan Tijms

Mysterious 4.4.1.20150109 Eclipse Luna update is SR1a

15 January 2015

Two days back I noticed Eclipse had a mysterious update available; Eclipse IDE for Java EE Developers, version 4.4.1.20150109-0740 with id “epp.package.jee”:

eclipse-luna-sr1a

Of course there was no info on what this update was about and Googling for it yielded no results. Googling again for it today gave a single hit:

download.eclipse.org/technology/epp/packages/luna/SR1a/p2.diff.txt

Looking at the URL revealed that “4.4.1.20150109-0740″ is the alternative universe version for what’s otherwise known as “Luna SR1a”. Googling for the latter gave some more results, particularly the following one:

Eclipse Ships Luna SR1a Git Security Release

A bit out of character, but the Eclipse organization even linked to this from their homepage!

Why it’s so difficult for Eclipse to show a description for their updates is still a small mystery, but at least the mystery of what “4.4.1.20150109-0740″ is about is now solved ;)

Arjan Tijms

Bridging Undertow’s authentication events to CDI

22 December 2014

Undertow’s native security system has an incredible useful feature that’s painfully missing in the security system of Java EE; authentication events.

While Java EE applications could directly use the Undertow events, it’s not directly clear how to do this. Furthermore having Undertow specific dependencies sprinkled throughout the code of an otherwise general Java EE application is perhaps not entirely optimal.

The following code shows how the Undertow dependencies can be centralized to a single drop-in jar, by creating an Undertow extension (handler) that bridges the native Undertow events to standard CDI ones. Upon adding such jar to a Java EE application, the application code only has to know about general CDI events.

First create the handler itself:

import io.undertow.security.api.NotificationReceiver;
import io.undertow.security.api.SecurityNotification;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import javax.enterprise.inject.spi.CDI;
import org.omnifaces.security.events.AuthenticatedEvent;
import org.omnifaces.security.events.LoggedOutEvent;
 
public final class AuthEventHandler implements HttpHandler {
 
    private final HttpHandler next;
    private static final SecurityNotificationReceiver NOTIFICATION_RECEIVER = new SecurityNotificationReceiver();
 
    public AuthEventHandler(final HttpHandler next) {
        this.next = next;
    }
 
    @Override
    public void handleRequest(HttpServerExchange exchange) throws Exception {
        exchange.getSecurityContext().registerNotificationReceiver(NOTIFICATION_RECEIVER);    
        next.handleRequest(exchange);
    }
 
    private static class SecurityNotificationReceiver implements NotificationReceiver {
 
        @Override
        public void handleNotification(final SecurityNotification notification) {
 
            switch (notification.getEventType()) {
                case AUTHENTICATED:
                    CDI.current().getBeanManager().fireEvent(new AuthenticatedEvent(notification, notification.getAccount().getPrincipal()));
                    break;
                case LOGGED_OUT:
                    CDI.current().getBeanManager().fireEvent(new LoggedOutEvent(notification, notification.getAccount().getPrincipal()));
                    break;
                default:
                    break;
            }
        }
    }
}

Note that the AuthenticatedEvent and LoggedOutEvent types come from OmniSecurity, but they are just used for the example. As the types contain no required logic, any simple type could be used..

Next register the handler in an extension as follows:

import io.undertow.servlet.ServletExtension;
import io.undertow.servlet.api.DeploymentInfo;
import javax.servlet.ServletContext;
 
public class UndertowHandlerExtension implements ServletExtension {
    @Override
    public void handleDeployment(final DeploymentInfo deploymentInfo, final ServletContext servletContext) {
        deploymentInfo
           .addInnerHandlerChainWrapper(handler -> new AuthEventHandler(handler));
    }
}

Finally register the extension by adding its fully qualified class name to the file /META-INF/services/io.undertow.servlet.ServletExtension.

Now jar the result up and add that jar to a Java EE application. In such application, the two authentication events shown in the source above can now be observed as follows:

@SessionScoped
public class SessionAuthListener implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    public void onAuthenticated(@Observes AuthenticatedEvent event) {
        String username = event.getUserPrincipal().getName();
        // Do something with name, e.g. audit, 
        // load User instance into session, etc
    }
 
    public void onLoggedOut(@Observes LoggedOutEvent event) {
        // take some action, e.g. audit, null out User, etc
    }
}

Experimenting with the above code proved that it indeed worked and it appears to be incredibly useful. Unfortunately this is now all specific to Undertow and thus only usable there and in servers that use Undertow (e.g. JBoss). It would be a real step forward for security in Java EE if it would support these simple but highly effective authentication events using a standardized API.

Arjan Tijms

Providing alternatives for JSF 2.3′s injected artifacts

6 November 2014

At the JSF 2.3 EG we’re currently busy with introducing the ability to inject several of JSF’s own artifacts in your own beans.

On the implementation side this is done via a dynamic CDI producer. There’s for instance a producer for the FacesContext, which is then registered via a CDI extension.

This can be tested via a simple test application. See these instructions for how to obtain a JSF 2.3 snapshot build and update GlassFish with it.

The test application will consist of the following code:

WEB-INF/faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config 
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd"
	version="2.3"
>
</faces-config>

This file is needed to activate injection of JSF artefacts. For backwards compatibility reasons this feature is only activated when running with a JSF 2.3 deployment descriptor. The second purpose of a (near) empty faces-config.xml is to signal JSF to automatically map the FacesServlet, so we don’t have to create a more verbose web.xml with an explicit mapping. (however the default mappings are not the best ones as the most obvious one, *.xhtml is missing. This is something we hope to rectify in JSF 2.3 as well)

WEB-INF/beans.xml
(empty)

An empty beans.xml is still needed in GlassFish 4.1 to actually enable CDI in a web archive.

index.xhtml

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:jsf="http://xmlns.jcp.org/jsf"
>
    <head jsf:id="head">
        <title>FacesContext inject test app</title>
    </head>
 
    <body jsf:id="body">
	   #{testBean.test}
    </body>
</html>

[java src]/test/TestBean.java

package test;
 
import javax.enterprise.context.RequestScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
 
@Named
@RequestScoped
public class TestBean {
 
    @Inject
    private FacesContext context;
 
    public String getTest() {
        return context.toString();
    }
}

Deploying this to our updated GlassFish and requesting http://localhost:8080/itest/index.jsf will result in something like the following:

com.sun.faces.context.FacesContextImpl@7c46fc07 

So injection works! Now what if we want to “override” the default producer provided by JSF, e.g. what if we want to provide our own alternative implementation?

The answer is to provide your own producer, but mark it as @Dependent, @Alternative and @Priority. E.g. add the following class to the files shown above:

[java src]/test/ContextProducer.java

package test;
 
import static javax.interceptor.Interceptor.Priority.APPLICATION;
 
import javax.annotation.Priority;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Alternative;
import javax.enterprise.inject.Produces;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextWrapper;
 
@Dependent
@Alternative
@Priority(APPLICATION)
public class ContextProducer {
 
    @Produces
    public FacesContext producer() {
        return new FacesContextWrapper() {
 
            @Override
            public String toString() {
                return "Still ours";
            }
 
            @Override
            public FacesContext getWrapped() {
                return FacesContext.getCurrentInstance();
            }
        };
    }
}

Then deploying this again and request http://localhost:8080/itest/index.jsf once more, will now result in the following:

Still ours 

As we see, the JSF provided producer can be overridden by standard CDI means.

The feature is not finalized yet so things may still change, but hopefully this gives some idea of what direction JSF 2.3 is moving in.

Arjan Tijms

Mysterious new Java EE 6 server shows up at Oracle certification pages

31 October 2014

Oracle publishes a page listing all officially certified Java EE servers. The page has been known to list a couple of fairly obscure servers; servers that indeed exist but seemingly nobody has ever heard of (as partly proven by a diverse range of surveys).

Recently a new mysterious server just showed up on this page: InforSuite Standard Edition V9.1

It’s not entirely clear when this was exactly added, but as I visited the page a few weeks before I guess it must have been certified at most a couple of weeks ago. At the very least it was added after last May, as I copied the entire list of servers there for an article I was writing and it sure wasn’t there then.

As for the component listed, it’s unfortunately the usual inconsistent table (every entry has a different table with different terms). It mentions using EclipseLink (JPA), Weld (CDI) and Hibernate Validation (Bean Validation), as well as Oracle and Oracle, which probably means the Oracle reference implementations of JAX-WS (Metro core) and JAXB.

It’s interesting that this late in the Java EE 6 cycle, with Java EE 7 having been released a while ago and Java EE 8 preparations being in full swing, there are still brand new Java EE 6 servers coming out.

Arjan Tijms

Eclipse 4.4 SR1 once again completely silently released

29 September 2014

Another year, another SR1 release, another deafining amount of silence; the Eclipse organization released maintance release one of Eclipse 4.4 three days ago.

As usual, there’s no notion of this event anywhere on the eclipse.org homepage. What counts this time is the Eclipse Newsletter about Project Quality and the fact that LocationTech has announced the 2014 Tour. The actual IDE that is Eclipse doesn’t seem to be that important.

As it appears, there were 131 bugs fixed for this release in the core of Eclipse.

Among others a high profile bug is fixed where Eclipse generated a bad class file and another bug where JSR 45 support (JSP debugging among others) was completely broken.

Furthermore several bugs related to Java 8 were fixed. As Eclipse uses its own compiler (JDT), supporting new language features is always extra difficult for Eclipse as compared to other IDEs that just use javac.

Eclipse 4.4 SR1 fixed some nasty issues with lambda type inference (and another one), deserialization, bridge methods, and explicit null-annotations.

Unfortunately, even with the focus on Java 8 fixes, a very basic and known type inference bug is still in Eclipse 4.4.1, as found out by my co-worker Jan Beernink:

luna_fail

This time around even the good people from the WTP project did not feel like posting about the SR1 event on their homepage. Fiddling with the friendly bugzilla URLs revealed a list of 32 bugs that are likely to be fixed in WTP 3.6.1, the version that should be the one that’s bundled with Eclipse 4.4.1.

Among the highlights of bugs that WTP 3.6.1 fixed is a fix for that fact the JSF EL validation is too strict and that when using the famous “Run on Server” feature, a wrong URL mapping is used.

Following the trend, community reporting is even lower than last year. This year there’s virtually no reporting at all. There’s a lone post from an Eclipse vendor, and that seems to be it.

Unfortunately Eclipse 4.4.1 also introduced a major new bug, one that’s appears right away when you startup a completely clean freshly downloaded instance:

java.lang.ClassCastException: org.eclipse.osgi.internal.framework.EquinoxConfiguration$1 cannot be cast to java.lang.String
	at org.eclipse.m2e.logback.configuration.LogHelper.logJavaProperties(LogHelper.java:26)
	at org.eclipse.m2e.logback.configuration.LogPlugin.loadConfiguration(LogPlugin.java:189)
	at org.eclipse.m2e.logback.configuration.LogPlugin.configureLogback(LogPlugin.java:144)
	at org.eclipse.m2e.logback.configuration.LogPlugin.access$2(LogPlugin.java:107)
	at org.eclipse.m2e.logback.configuration.LogPlugin$1.run(LogPlugin.java:62)
	at java.util.TimerThread.mainLoop(Timer.java:555)
	at java.util.TimerThread.run(Timer.java:505)

It seems clear that SR releases aren’t that exciting, but the complete lack of attention to them and the completely silent releases of what should be the most important product that the Eclipse organization delivers remains a curious thing.

Update

Maybe after reading this article (who knows ;)), but a few days later the Eclipse organisation did finally post about the release event, and the following appeared on the eclipse.org homepage:

2014/09/29
Eclipse Luna SR1 Now Available
The SR1 release of the Eclipse Luna release train is now available for download.

BalusC joins JSF 2.3 EG

12 September 2014

A few weeks ago zeef.com joined the JCP:

Via zeef.com, BalusC (Bauke Scholtz) applied this morning for membership of the JSF EG and was accepted later on the day by spec lead Ed Burns:

Bauke is well known for his many answers on StackOverflow, his blog and of course his work for the JSF utility library OmniFaces.

As members of the JSF 2.3 EG, Bauke and myself (I joined the JSF EG as well) will be looking among others at the possibility of bringing over things from OmniFaces into the JSF core spec and overall help out with taking JSF to the next level. What will eventually end up in JSF is of course subject to community feedback and EG negotiation and approval.

At any length, both Bauke and I are looking forward to working together with the other EG members and contributing to the JSF core spec :)

Arjan Tijms

Dynamic CDI producers

1 August 2014

CDI has the well known concept of producers. Simply put a producer is a kind of general factory method for some type. It’s defined by annotating a method with @Produces. An alternative “factory” for a type is simply a class itself; a class is a factory of objects of its own type.

In CDI both these factories are represented by the Bean type. The name may be somewhat confusing, but a Bean in CDI is thus not directly a bean itself but a type used to create instances (aka a factory). An interesting aspect of CDI is that those Bean instances are not just internally created by CDI after encountering class definitions and producer methods, but can be added manually by user code as well.

Via this mechanism we can thus dynamically register factories, or in CDI terms producers. This can be handy in a variety of cases, for instance when a lot of similar producer methods would have to be defined statically, or when generic producers are needed. Unfortunately, generics are not particularly well supported in CDI. Instead of trying to create a somewhat generic producer an alternative strategy could be to actually scan which types an application is using and then dynamically create a producer for each such type.

The following code gives a very bare bones example using the plain CDI API:

public class DynamicIntegerProducer implements Bean<Integer> {
 
    @SuppressWarnings("all")
    public static class DefaultAnnotationLiteral extends AnnotationLiteral<Default> implements Default {
        private static final long serialVersionUID = 1L;
    }
 
    @Override
    public Class<?> getBeanClass() {
        return Integer.class;
    }
 
    @Override
    public Set<Type> getTypes() {
        return new HashSet<Type>(asList(Integer.class, Object.class));
    }
 
    @Override
    public Integer create(CreationalContext<Integer> creationalContext) {
        return new Integer(5);
    }
 
    @Override
    public Set<Annotation> getQualifiers() {
        return singleton((Annotation) new DefaultAnnotationLiteral());
    }
 
    @Override
    public Class<? extends Annotation> getScope() {
        return Dependent.class;
    }
 
    @Override
    public Set<Class<? extends Annotation>> getStereotypes() {
        return emptySet();
    }
 
    @Override
    public Set<InjectionPoint> getInjectionPoints() {
        return emptySet();
    }
 
    @Override
    public boolean isAlternative() {
        return false;
    }
 
    @Override
    public boolean isNullable() {
        return false;
    }
 
    @Override
    public String getName() {
        return null;
    }
 
    @Override
    public void destroy(Integer instance, CreationalContext<Integer> creationalContext) {
 
    }
}

There are a few things to remark here. First of all the actual producer method is create. This one does nothing fancy and just returns a new Integer instance (normally not a good idea to do it this way, but it’s just an example). The getTypes method is used to indicate the range of types for which this dynamic producer produces types. In this example it could have been deducted from the generic class parameter as well, but CDI still wants it to be defined explicitly.

The getQualifiers method is somewhat nasty. Normally if no explicit qualifiers are used in CDI then the Default one applies. This default is however not implemented in the core CDI system it seems, but is done by virtue of what this method returns. In our case it means we have to explicitly return the default qualifier here via an AnnotationLiteral instance. These are a tad nasty to create, as they require a new class definition that extends AnnotationLiteral and the actual annotation needs to be present as both a (super) interface AND as a generic parameter. To add insult to injury, Eclipse in particular doesn’t like us doing this (even though it’s the documented approach in the CDI documentation) and cries hard about this. We silenced Eclipse here by using the @SuppressWarnings(“all”) annotation. To make the code even more nasty, due to the way generics and type inference work in Java we have to add an explicit cast here (alternatively we could have used Collections.<Annotation>singleton).

For the scope we can’t return a null either, but have to return the CDI default as well if we want that default. This time it’s an easy return. For the scope and stereo types we can’t return a null if we don’t use them, but have to return an empty set. The isNullable method (deprecated since CDI 1.1) can return false. Finally, getName is the only method that can return a null.

Dynamic producers like this have to be added via a CDI extension observing the AfterBeanDiscovery event:

public class DynamicProducerExtension implements Extension {
    public void afterBean(final @Observes AfterBeanDiscovery afterBeanDiscovery) {
        afterBeanDiscovery.addBean(new DynamicIntegerProdcuer());
    }
}

As with all CDI extensions the extension class has to be registered by putting its FQN in META-INF/services/javax.enterprise.inject.spi.Extension.

After doing this, injection can be done as usual, e.g.:

@Singleton
@Startup
public class TestBean {
 
    @Inject
    private Integer integer;
 
    @PostConstruct
    public void init() {
        out.println(integer);
    }
}

Deploying an application with only the code shown in this post will print 5 in the logs ;)

Arjan Tijms

css.php best counter