Weld 5.0.0.Final

2022-4-29   release   Matej Novotny

CDI 4 has passed its Final ballot and is now available in Maven Central. Some of you may have played with it already, but where is the fun in it, if you don’t have a Final implementation, right? Have no fear, Weld 5 Final is here!

As usual, there is Weld 5.0.Final API as well as Weld 5.0.0.Final core impl.

It is very much the same as CR2, with some additional tweaks and fixes that came to light when working on integrations within EE servers. That’s right, EE servers are already making progress towards integrating CDI 4 and Weld 5. Folks over at Open Liberty did their Weld 5 homework about a week ago and WildFly now has a pending pull request that adds missing bits for CDI 4 support. It might still be a while before there is a Beta WildFly release, but if you have the nerves, you can build the SNAPSHOT at least.

Back on the topic of changes, here is a list of fixes from CR2 to Final:

  • Self-interception can now be used on protected methods, params and return types (WELD-2712)

  • Rewieved Weld examples and made sure they run for EE 10 (WELD-2708)

  • Review Weld 5 documentation (WELD-2696)

    • Note that the servlet part is still outdated and being worked on as we need to see if there is workable EE 10 variant, see WELD-2716

    • We expect that this will be sorted by the time we ship 5.0.1.Final

  • Firing of the Startup event for web modules can happen too early (WELD-2717)

  • Synthetic beans coming from Build Compatible extension should be registered under their respective extensions (WELD-2718)

  • Exceptions thrown during execution of Build Compatible extensions now correctly preserve their cause (WELD-2710)

  • Some of our SE testing was being skipped ever since Groovy dependency update, this is now corrected (WELD-2714)

Weld 5.0.0.CR2

2022-3-23   release   Matej Novotny

Final ballot of CDI 4 has uncovered untested and unimplemented area in the newly added Startup and Shutdown events.

Our previous release was guilty of not supporting this properly, hence here comes Weld API 5.0.CR2 and Weld Core 5.0.0.CR2.

Weld now automatically fires these events and the JIRA issue for this can be seen here (WELD-2709). However, integrators can choose to override this behavior and fire both events themselves in case there is more bootstrapping logic that needs to come together before the container is deemed ready. The API interface org.jboss.weld.bootstrap.api.Environment allows implementors to override a specific method which will then prevent Weld from handling these events.

Weld 5.0.0.CR1

2022-2-23   release   Matej Novotny

Weld 5 now has its first candidate release; Weld API 5.0.CR1 and Weld Core 5.0.0.CR1 are headed towards Maven Central.

This release has only minor differences from the Beta but it is a testable basis for Final specification release. Here is a quick overview:

  • Correct default package detection inside ProxyFactory (WELD-2704)

  • Use secure actions when obtaining constructors via reflection in LiteExtensionTranslator (WELD-2705)

  • Dozens of dependabot updates for various dependencies

  • Updated to the latest released CDI version (4.0.0-RC5) and latest CDI TCK version (4.0.0.RC6)

Weld 4.0.3.Final and 3.1.9.Final

2022-2-16   release   Matej Novotny

Weld 3.1.9.Final for Jakarta EE 8 and Weld 4.0.3.Final for Jakarta EE 9 are now available.

Weld 3.1 and Weld 4.0 now enter a maintenance mode - there will be no further active development on these branches. Instead, the focus will be on Weld 5/EE 10 and beyond.

Here is a brief list of notable changes; all of these are present in both Weld versions:

  • Gracefully handle non-existing classpath entries in SE (WELD-2605)

  • Proxies for classes starting with jakarta.* now have Weld proxy prefix instead (WELD-2684)

  • WeldInstance.Handle#get() could incorrectly return the same instance even after destroying underlying contextual reference (WELD-2687)

  • Fixed BeanConfigurator#produceWith() leaking dependent bean under certain conditions (WELD-2693)

  • Correct default package detection inside ProxyFactory (WELD-2704)

  • Several minor changes with regard to testing setup and update configurations (WELD-2706 and WELD-2707)

Last but not least, for those using WildFly, I would recommend taking a look into their release plan for 2022. It details which WildFly is the last for EE 8 and EE 9 and what happens going onwards. Weld is of course going to keep up the pace and we are working on integrating Weld 5 into Wildfly.

Weld 5.0.0.Beta1

2022-1-24   release   Matej Novotny

Some of you might have noticed that Weld already had some version 5 releases, namely two Alphas. Those were a work-in-progress implementations so I didn’t post any actual release notes as the specification was still undergoing changes. CDI 4 is now in very much ready-to-fly state as its first CR release has recently landed in Maven Central. Therefore, here we are with a proper release of Weld API 5.0.Beta5 and Weld Core 5.0.0.Beta1 which implements all the bits and pieces of CDI 4.0 plus brings a few more changes and deprecation removals.

This post will try to cover Weld-side of things meaning anything that changed and is Weld specific or influences integrators in any way. If you want to learn what’s new in CDI 4.0, I suggest taking a look at this detailed article I wrote some time ago. It provides a good overview of all major changes, all of which are implemented in this Weld release. In case you want to check out the list of JIRA issues for Weld releases, the last chapter will provide links for both Alpha releases as well as this Beta release. Last but not least, you can also reach out to us via Gitter channel or mailing list.

Without further ado, let’s dive into it!

Target JDK version for Weld 5 (and for CDI 4) is now 11

Therefore, JDK 11 is now the minimal version required to run Weld. This is basically a requirement for all Jakarta EE 10 specifications. On the other hand, Weld 5 is also tested against and supports JDK 17 as well.

Weld 5 is no longer a multi-release (MR) JARs

As you might know, Weld 3 and 4 are running some different class defining strategies for JDK 8 or 11+ resulting in an MR JAR solution. Since JDK 11 is the basis, this is no longer needed and similar workarounds were removed from code.

Deprecations and removals

Here is a list of all changes of this nature within Weld APIs:

  • Multiple methods from org.jboss.weld.serialization.spi.ProxyServices were removed.

    • If you are an integrator, you probably implemented this interface at some point in time; these methods weren’t used by Weld anyway, so they are now gone for good.

    • Here is a link to the issue removing it.

  • Any integrators basing their implementations of Jandex likely implemented ClassFileInfo; its isTopLevelClass() has been removed.

    • Note that this method was redundant and can be replaced by getClassNestingType().

    • This was removed as part of the above mentioned issue.

  • WeldInstance.Handler class is now deprecated and so are multiple methods returning this type from WeldInstance

CDI has had a similar cleanup and some long deprecated API methods were removed; glance at this GitHub issue if you want to learn more about that.

Empty `beans.xml interpretation

There is one breaking change in CDI 4.0 that should be mentioned here - change of default interpretation of empty beans.xml descriptor. Up until CDI 3.0, leaving this file empty meant discovery mode all whereas starting with CDI 4 it now defaults to annotated discovery mode. As per specification, in all discovery mode, all classes in bean archive are scanned and if fitting, turned into beans. However, annotated discovery mode only scans classes with bean defining annotations. Therefore, this change can be breaking for lots of applications using empty beans.xml and relying on CDI to discover classes without annotations. In order to ease the transition to this new default, CDI 4 specification says the following:

For compatibility with CDI versions prior to 4.0, CDI Full products must contain an option that causes an archive with empty beans.xml to be considered an explicit bean archive.

This option is vendor-dependent and integrators needs to define how to achieve it in their frameworks/platforms. That being said, Weld has been updated to allow for this. If you are using Weld tooling to parse beans.xml, chances are, you’re doing one of these:

  • Directly invoking parser via org.jboss.weld.xml.BeansXmlStreamParser.

    • BeansXmlStreamParser now has new constructor methods which allow passing BeanDiscoveryMode parameter telling Weld how to interpret empty beans.xml.

    • All former constructors were retained and default to BeanDiscoveryMode.ANNOTATED.

  • Indirectly invoking it via an implementation of org.jboss.weld.bootstrap.api.Bootstrap and its parse methods.

    • New variantions of the parse methods were added and accept BeanDiscoveryMode parameter telling Weld how to interpret empty beans.xml.

    • All former variantion of parse methods were retained and default to BeanDiscoveryMode.ANNOTATED.

This should give integrators enough leeway to implement the backward compatibility switch.

Weld versus CDI Lite versus CDI Full

By far the biggest change in CDI 4.0 is the introduction of CDI Lite. At this point I should reiterate that I highly recommend looking this article if you don’t know what CDI Lite is. In short, CDI Lite is a feature subset of CDI Full that broadens the amount of environments in which CDI can execute; more presicely, it enables CDI in build time oriented frameworks such as Micronaut or Quarkus. What does that means for Weld users? Nothing much, Weld is and will be a runtime oriented implementation and you can keep using CDI as you did up until now. More precisely, Weld is so called CDI Full implementation meaning it provides each and every CDI feature and while there were some deprecations and removals, the rest stays the same.

Build Compatible Extensions

One of the notable additions to CDI Lite (and therefore into CDI Full as well) were Build Compatible Extensions (BCE). These are akin to Portable Extensions but tuned in a way so that they can be used in build time oriented environments as well. Along with it comes a different language model because AnnotatedType and friends are reflection-heavy and not a good fit for that API. If you want to learns more, here is an excellent article by Ladislav Thon that covers how they work.

From Weld perspective, you can use BCE as much as you like although they are also executed at runtime, just as Portable Extensions are. It is still recommended to use Portable Extensions if possible because BCE are (in Weld) implemented via Portable Extensions. That being said, if you have some portability demands between Lite and Full, you should be able to use BCE as much as you like.

Integrators - how to make Weld understand Build Compatible Extensions?

This part focuses mainly on integrators and describes how Weld implements Build Compatible Extensions and what needs to be done by integrators in order to fully support CDI Lite.

weld-lite-extension-translator module

Weld 5 has a new module that enables Build Compatible Extensions (BCE) and the new language model that goes along with it - weld-lite-extension-translator. GAV of this new artifact is org.jboss.weld:weld-lite-extension-translator:5.0.0.Beta1. As I mentioned in previous point, BCE are executed via a Portable extension. More precisely, the key class is WeldLiteExtensionTranslator.

Just like any Portable extension, it needs an entry in META-INF or an instance of this extensions has to be added programmaticaly during Weld bootstrap. This is where it gets tricky; it doesn’t work out of the box in all environments!

  • Weld SE - works out of the box, the extension is automagically added

  • Weld Servlet - works out of the box, the extensions is automagically added

  • EE - doesn’t work without integrator registering the extension

  • Any other custom integration - doesn’t work without integrator registering the extension

There is of course a reason for it - complex structured deployments (such as EAR or WAR) and the fact that Weld alone cannot know the deployment well enough to make sure this extension wouldn’t be registered multiple times. On top of that, you might also want to avoid registering this extension if there are no BCE found inside the deployment which can also be dependent on how the given platform performs such discovery. Therefore, Weld leaves it up to the integrator (WildFly, GF, Liberty,…​) to identify where and when to register this extension for each deployment.

Registering LiteExtensionTranslator

Registering the LiteExtensionTranslator can be as easy as adding a META-INF entry with it into some archive in the deployment. An example of this would be arquillian-container-weld, a test container for Weld applications. As you can see from this pull request, it basically adds a META-INF entry which is sufficient to support new extension model. Since it a test tool, the extension is always registered without any attempt to optimize it.

The above solution is nice and clean, but won’t cut it for any EE integrators. Instead, you will want to register this extension very similarly to how you currently register ProbeExtension - add it programmatically as part of the CDI deployment. As mentioned above, this extension should to be registered at most once per deployment, so I’d recommend welding (pun intended) this directly into your org.jboss.weld.bootstrap.spi.CDI11Deployment implementation. Because WildFly does not yet have a public branch with this, I can at least point to how it registers ProbeExtension. With a little bit of digging, it boils down to creating CDI11Deployment impl with list of extensions already containing this one.

Which brings us to the second point - I’d recommend integrators to optimize this process and only register/include LiteExtensionTranslator when there is at least one BCE present in any given deployment. The reason being that this extension has to monitor a very wide range of events including ProcessAnnotatedType<?> for all types in order to properly implement BCE. Many integrators can perform BCE detection in their own ways (such as Jandex in WildFly) but for those that want a generic solution, take a look at org.jboss.weld.lite.extension.translator.BuildCompatibleExtensionLoader which is a utility class alowing to perform a standard service discovery process with given ClassLoader and returns the set of discovered BCE classes. You can then instantiate LiteExtensionTranslator via a constructor that takes this set as an input; or skip registering it if you haven’t found any BCE at all.

TCK structural changes and lang model TCKs

Few paragraphs above I mentioned new language model used by Build Compatible Extensions. Obviously, this needed some testing and so CDI TCK has a separate module for it; see lang-model module and its README. Weld tests and passes these TCKs via lang-model-tck module.

Next change was a separation of tests between pure CDI tests and tests requiring other Jakarta EE technologies such as JSF, EL and other. Many of these are candidates for move into their respective specifications but are for now still hosted in CDI TCK. All of these tests now reside under a separate module with GAV jakarta.enterprise:cdi-tck-web-impl.

Lastly, due to the split between CDI Lite and Full and the ability to have CDI implementations only for Lite, all TCKs had to be reviewed and a new test category was added - cdi-full. It is easy to guess that this category was assigned to tests that are supposed to only execute in CDI Full implementations; i.e. tests containing features that aren’t present in CDI Lite. Weld, as noted before, is a CDI Full implementation and as such passes all TCKs. The current setup used for TCK execution can be read from this POM file.

More in-depth overview of resolved issues in Weld 5

Finally, for those who would like to inspect a more detailed list of changes, here are links to release notes of all version 5 releases up to and including Beta1: