Red Hat JBoss EAP Application Migration from Jakarta EE 8 to EE 10
Overview
Red Hat JBoss Enterprise Platform 8 provide support for Jakarta EE 10. Jakarta EE 10 brings a very large change to Jakarta EE compared to the Jakarta EE 8 specifications supported by EAP 7. In this article we discuss the compatibility-impacting differences in the EE APIs that application developers should be aware of when preparing to migrate their applications from EAP 7 to EAP 8.
Note: The focus of this article is on what the differences are between EE 8 and EE 10 that an application migration to EAP 8 may need to deal with, and not on how to do the migration. For more information on EAP 7 to EAP 8 application migration in general and the tooling Red Hat provides to assist with this, see also Content from red.ht is not included.How to migrate apps from JBoss EAP 7.x to JBoss EAP 8.0.
The javax to jakarta Package Namespace Change
By far the largest compatibility-impacting difference between Jakarta EE 8 and EE 10 is the renaming of the EE API Java packages from javax.* to jakarta.*. Following the move of Java EE to the Eclipse Foundation and the establishment of Jakarta EE, Content from blogs.eclipse.org is not included.Eclipse and Oracle agreed that the Jakarta EE community cannot evolve the javax package namespace. Therefore, in order to be able to continue to evolve the EE APIs, beginning with Jakarta EE 9 the packages used for all EE APIs have changed from javax.* to jakarta.*. (Note that this change does not affect javax packages that are part of Java SE.)
Adapting to this namespace change is the biggest change involved in migrating an application from EAP 7 to EAP 8. Applications migrating to EE 10 will need to:
- Update any import statements or other source code uses of EE API classes from the
javaxpackage tojakarta. - Update the names of any EE-specified system properties or other configuration properties whose names that begin with
javax.to instead begin withjakarta.. - For any application-provided implementations of EE interfaces or abstract classes that are bootstrapped using the
java.util.ServiceLoadermechanism, the name of the resource that identifies the implementation class will need to be changed fromMETA-INF/services/javax.[rest_of_name]toMETA-INF/services/jakarta.[rest_of_name].
Note: The Red Hat Migration Toolkit can assist in updating the namespaces in the application source code; see How to use Red Hat Migration Toolkit for Auto-Migration of an Application to the Jakarta EE 10 Namespace for more information. For cases where source code migration is not an option, the open source Content from github.com is not included.Eclipse Transformer project provides bytecode transformation tooling to transform existing Java archives from the javax namespace to jakarta.
Other Changes
Besides the package namespace change, applications written for earlier EE versions may need to adapt to changes made in a number of specifications included in Jakarta EE 10 . The following sections describe these. The bulk, but not all, of these are removals of long-deprecated API elements.
Note that in the following sections, for any mentions of API elements that have been removed that use the javax namespace, the equivalent removal has also been done in the jakarta namespace that was used in Jakarta EE 9. So, if you have updated your application to replace the javax namespace with jakarta, assume that the items that mention javax apply to your application as well.
Jakarta Contexts and Dependency Injection Bean Discovery
As discussed in the second paragraph of the Content from jakarta.ee is not included.CDI 4.0 spec change notes, the default behavior for discovering CDI beans in a deployment with an empty beans.xml file has changed from all to annotated. This means for such a deployment only deployment classes with a Content from jakarta.ee is not included.bean defining annotation will be discovered by CDI. If all application classes used as beans have such an annotation, this CDI change will have no impact. Otherwise, application deployment may fail when CDI cannot find a type that provides a particular bean.
If your application is impacted by this change, you have several options:
- Leave the beans.xml file empty but add a bean defining annotation to all classes that need it.
- Leave the classes unchanged but change the beans.xml file from being empty to one with the following content:
<beans bean-discovery-mode="all"></beans> - Leave the application unchanged, but change the server’s weld subsystem configuration to restore handling of empty beans.xml files back to the EAP 7 behavior. (Note that this setting will affect all deployments on the server.) For example, with the CLI:
/subsystem=weld:write-attribute(name=legacy-empty-beans-xml-treatment,value=true)
CDI API Changes
Jakarta Contexts and Dependency Injection 4.0 removed a number of deprecated API elements:
- The
javax.enterprise.inject.spi.Bean.isNullable()method has been removed. This method has always returnedfalsefor many years now, so applications that call it can replace the call withfalseor remove any branching logic and just retain the contents of thefalsebranch. - The
javax.enterprise.inject.spi.BeanManager.createInjectionTarget(AnnotatedType)method has been removed. Replace this method call with withBeanManager.getInjectionTargetFactory(AnnotatedType)and use the returned factory to create injection targets. See Content from jakarta.ee is not included.Obtaining an InjectionTarget for a class in the Jakarta Contexts and Dependency injection specification for more information. - The
javax.enterprise.inject.spi.BeanManager.fireEvent(Object, Annotation)method has been removed. UseBeanManager.getEvent()as an entry point to a similar API. See Content from jakarta.ee is not included.Firing an event in the Jakarta Contexts and Dependency injection specification for more information. - The javax.enterprise.inject.spi.BeforeBeanDiscovery.addAnnotatedType(AnnotatedType) method has been removed. If your application is calling this method you can replace it with a call to
BeforeBeanDiscovery.addAnnotatedType(AnnotatedType, (String) null).
Jakarta Enterprise Beans
Java SE 14 has removed the java.security.Identity class, so use of it has been removed from the Jakarta Enterprise Beans 4.0 API.
- The deprecated
javax.ejb.EJBContext.getCallerIdentity()method has been removed. UseEJBContext.getCallerPrincipal()instead, which returns ajava.security.Principal. - The deprecated
javax.ejb.EJBContext.isCallerInRole(Identity role)method has been removed. UseEJBContext.isCallerInRole(String roleName)instead.
The Jakarta XML RPC specification has been removed from the Jakarta EE 10 Full Platform, so the javax.ejb.SessionContext.getMessageContext() method that returned a javax.xml.rpc.handler.MessageContext has been removed. The Jakarta XML RPC specification was optional in Jakarta EE 8, and Red Hat JBoss EAP 7 does not support it and any use of it would have thrown an IllegalStateException, so this EJB API change is not expected to affect any existing applications running on EAP 7.
The deprecated javax.ejb.EJBContext.getEnvironment() method has been removed. Use the JNDI naming context java:comp/env to access the enterprise bean's environment.
Jakarta Expression Language
The incorrectly spelled javax.el.MethodExpression.isParmetersProvided() method has been removed. Use MethodExpression.isParametersProvided() instead.
Jakarta JSON Binding
By default, types annotated with the jakarta.json.bind.annotation.JsonbCreator annotation no longer require all parameters to be present in the JSON content. Default values will be used if the JSON being parsed is missing one of the parameters. The EE 8 behavior of requiring that all parameters be present in the JSON can be turned on by calling jakarta.json.bind.JsonbConfig().withCreatorParametersRequired(true).
Jakarta Server Faces
There have been some significant removals of long-deprecated functionality in Faces 4.0
Faces and JSPs
The JSP support in Jakarta Server Faces has been deprecated since JSF 2.0. In its place, Facelets has been designated as the preferred View Definition Language. With Jakarta Server Faces 4.0, JSP support has been completely removed, so any applications using JSP for templating its Faces views will need to be modified to use Facelets. In most cases, these applications can be easily identified by a mapping in web.xmlof the FacesServlet to the *.jsp suffix.
Faces Managed Beans
The deprecated Jakarta Server Faces-specific managed bean concept has been removed in Faces 4.0, in favor of Jakarta Contexts and Dependency Injection (CDI) beans. Applications using Faces managed beans (i.e. classes annotated with javax.faces.bean.ManagedBean or referenced in a managed-bean element in faces-config.xml) may need to make the following changes:
- Classes annotated with
javax.faces.bean.ManagedBeanor referenced in amanaged-beanelement infaces-config.xmlshould instead be annotated withjakarta.inject.Named, and anymanaged-beanelement infaces-config.xmlshould be removed. - Members annotated with the
javax.faces.bean.ManagedPropertyannotation should usejakarta.faces.annotation.ManagedPropertyinstead, along with thejakarta.inject.Injectannotation. To get a startup semantic similar to the oldjavax.faces.bean.ManagedBean(name=“foo”, eager=true)add apublic void xxx(@Observes jakarta.enterprise.event.Startup event)method or apublic void xxx(@Observes @Initialized(ApplicationScoped.class) Object context)method. Thejakarta.enterprise.event.Startupoption is new in CDI 4.0. - Use of the
javax.faces.bean.ApplicationScopedannotation should be replaced withjakarta.enterprise.context.ApplicationScoped. - Use of the
javax.faces.bean.CustomScopedannotation should be replaced with CDI custom scopes andjakarta.enterprise.context.spi.Context. See Content from jakarta.ee is not included.Defining new scope types and Content from jakarta.ee is not included.The Context Interface in the CDI 4.0 specification for more details. - Use of the
javax.faces.bean.NoneScopedannotation should be replaced withjakarta.enterprise.context.Dependent, which is a CDI built-in scope with approximately similar semantics. - Use of the
javax.faces.bean.RequestScopedannotation should be replaced withjakarta.enterprise.context.RequestScoped. - Use of the
javax.faces.bean.SessionScopedannotation should be replaced withjakarta.enterprise.context.SessionScoped.
Other Faces API Changes
The javax.faces.bean.ViewScoped annotation has been removed. Use jakarta.faces.view.ViewScoped instead.
The javax.faces.view.facelets.ResourceResolver and javax.faces.view.facelets.FaceletsResourceResolver annotations have been removed. For any ResourceResolvers in your application, implement the jakarta.faces.application.ResourceHandler interface and register the fully qualified class name of the implementation via in the application/resource-handler element in faces-config.xml.
Jakarta Servlet
Jakarta Servlet 6.0 removes a number API classes and methods that were deprecated in Servlet 5.0 and earlier, mostly in the Servlet 2.x releases.
The javax.servlet.SingleThreadModel marker interface has been removed and servlets that implement this interface should remove the interface declaration and ensure that the servlet code properly guards state and other resource access against concurrent access, for example by avoiding the usage of an instance variable or synchronizing the block of code accessing resources. However, it is strongly recommended that developers not synchronize the service method (or methods like doGet and doPost that it dispatches to) because of the detrimental effect of such synchronization on performance.
The javax.servlet.http.HttpSessionContext interface has been removed, along with the javax.servlet.http.HttpSession.getSessionContext() method. Since Servlet 2.1 there have been no use cases for this interface as its implementations were required by spec not to provide any usable data.
The javax.servlet.http.HttpUtils utility class has been removed. Applications should use the ServletRequest and HttpServletRequest interfaces instead of these methods it provided:
parseQueryString(String s)andparsePostData(int len, ServletInputStream in)-- UseServletRequest.getParameterMap(). If an application needs to differentiate between query string parameters and request body parameters it will need to implement code to do that itself, perhaps by parsing the query string itself.getRequestURL(HttpServletRequest req)-- UseHttpServletRequest.getRequestURL().
Finally, a number of miscellaneous methods and constructors have been removed:
| Class/Interface | Removed | Use Instead |
|---|---|---|
javax.servlet.ServletContext | getServlet(String name) | no replacement |
getServlets() | no replacement | |
getServletNames() | no replacement | |
log(Exception exception, String msg) | log(String message, Throwable throwable) | |
javax.servlet.ServletRequest | getRealPath(String path) | ServletContext.getRealPath(String path) |
javax.servlet.ServletRequestWrapper | getRealPath(String path) | ServletContext.getRealPath(String path) |
javax.servlet.UnavailableException | getServlet() | no replacement |
UnavailableException(Servlet servlet, String msg) | UnavailableException(String) | |
UnavailableException(int seconds, Servlet servlet, String msg) | UnavailableException(String, int) | |
javax.servlet.http.HttpServletRequest | isRequestedSessionIdFromUrl() | isRequestedSessionIdFromURL() |
javax.servlet.http.HttpServletRequestWrapper | isRequestedSessionIdFromUrl() | isRequestedSessionIdFromURL() |
javax.servlet.http.HttpServletResponse | encodeUrl(String url) | encodeURL(String url) |
encodeRedirectUrl(String url) | encodeRedirectURL(String url) | |
setStatus(int sc, String sm) | sendError(int, String) | |
javax.servlet.http.HttpServletResponseWrapper | encodeUrl(String url) | encodeURL(String url) |
encodeRedirectUrl(String url) | encodeRedirectURL(String url) | |
setStatus(int sc, String sm) | sendError(int, String) | |
javax.servlet.http.HttpSession | getValue(String name) | getAttribute(String name) |
getValueNames() | getAttributeNames() | |
putValue(String name, Object value) | setAttribute(String name, Object value) | |
removeValue(String name) | removeAttribute(String name) |
Jakarta Soap with Attachments
Support for provider lookup through a jaxm.properties file has been removed.
The deprecated javax.xml.soap.SOAPElementFactory class has been removed. Use jakarta.xml.soap.SOAPFactoryfor creating SOAPElements.
| SOAPElementFactory method | SOAPFactory equivalent |
|---|---|
newInstance() | newInstance() |
create(Name) | createElement(Name) |
create(String) | createElement(String) |
create(String, String, String) | createElement(String, String, String) |
Jakarta XML Binding
The XML namespace that should be used in xml binding files has changed. The http://java.sun.com/xml/ns/jaxb namespace should be replaced with https://jakarta.ee/xml/ns/jaxb.
The deprecated javax.xml.bind.Validator interface has been removed, as has the associated javax.xml.bind.JAXBContext.createValidator() method. To validate marshalling and unmarshalling operations provide a javax.xml.validation.Schema to jakarta.xml.bind.Marshaller.setSchema(Schema).
Support for compatibility with JAXB 1.0 has been removed.
Deprecated steps in the JAXBContext implementation lookup algorithm have been removed. Searches for implementation class names through jaxb.properties files, javax.xml.bind.context.factory or jakarta.xml.bind.JAXBContext properties and /META-INF/services/javax.xml.bind.JAXBContext resource files have been dropped. For details of the current implementation discovery algorithm, see the Content from jakarta.ee is not included.Jakarta XML Binding 4.0 specification.
The generics requirements for a number of methods in the javax.xml.bind.Marshaller interface have changed:
| Jakarta XML Binding 2.3 / 3.0 | Jakarta XML Binding 4.0 |
|---|---|
<A extends XmlAdapter> void setAdapter(A adapter) | <A extends XmlAdapter<?, ?>> void setAdapter(A adapter) |
<A extends XmlAdapter> void setAdapter(Class<A> type, A adapter) | <A extends XmlAdapter<?, ?>> void setAdapter(Class<A> type, A adapter) |
<A extends XmlAdapter> A getAdapter(Class<A> type) | <A extends XmlAdapter<?, ?>> A getAdapter(Class<A> type) |
Beyond the changes in the Jakarta XML Binding API, there have also been significant package name changes in the implementation library EAP 8 uses, which may affect some applications that access the implementation library directly:
- Any use of classes in the
com.sun.xml.bindpackage should be replaced by classes in theorg.glassfish.jaxb.runtimepackage. Classes in sub-packages ofcom.sun.xml.bindshould be replaced with classes in correspondingorg.glassfish.jaxb.runtimesub-packages. - For
jakarta.xml.bind.Marshallerproperty settings, change the property constant name fromcom.sun.xml.bind.*toorg.glassfish.jaxb.*. For example,
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper)becomesmarshaller.setProperty("org.glassfish.jaxb.namespacePrefixMapper", mapper).