Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [hudson-dev] Supporting Java EE 7 (CDI 1.1) and later

In addtion to the bug mentioned previously, I found another bug <https://java.net/jira/browse/JERSEY-1115> which may be related.  It was fixed in version 1.17 and affected Jersey from version 1.12 through 1.16.


On Mon, Apr 20, 2015 at 11:23 AM, Kaz Nishimura <kazssym@xxxxxxxxx> wrote:
If I read the documentation of WildFly correctry, WildFly does not use Jersey as its JAX-RS implementation but RESTEasy, so this exception must not occur in WildFly.  I suspect it is caused by Jersey (version 1.5) contained in Rest Plugin, since if I disabled it in the plugin manager, Hudson started without errors.

The bug in Jersey was fixed in version 1.12 according to this report <https://java.net/jira/browse/JERSEY-601> and affected from verstion 1.5 to 1.11.  So just updating Jersey in Rest Plugin may resolve this problem.


On Thu, Mar 19, 2015 at 4:49 AM, Winston Prakash <winston.prakash@xxxxxxxxx> wrote:
Hi Kaz,

Everything seems to work fine on Glassfish 4.1. But one of our QA Engineers, Latha Amujuri, reported the following.
She tried it on WildFly (JBoss 8.2.0) and it did not work. Can you please take a look

-->

I just tried Wildfly 8.2.0 with JDK 1.8.0_40 with an existing Hudson home folder from 3.2.0. The main Hudson page does not load with the following exception:
I saw the same exception with Glassfish 4.1 as well but the main page loaded and it did not seem to affect any functionality.
java.lang.RuntimeException: javax.naming.NameNotFoundException: com.sun.jersey.config/CDIExtension -- service jboss.naming.context.java."com.sun.jersey.config".CDIExtension
com.sun.jersey.server.impl.cdi.CDIExtension.getInitializedExtension(CDIExtension.java:174)
com.sun.jersey.server.impl.cdi.CDIComponentProviderFactory.<init>(CDIComponentProviderFactory.java:92)
com.sun.jersey.server.impl.cdi.CDIComponentProviderFactoryInitializer.initialize(CDIComponentProviderFactoryInitializer.java:75)
com.sun.jersey.spi.container.servlet.WebComponent.configure(WebComponent.java:573)
com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.configure(ServletContainer.java:311)
com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:605)
com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:213)
com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:373)
org.hudsonci.rest.server.internal.jersey.RestServlet.init(RestServlet.java:113)
javax.servlet.GenericServlet.init(GenericServlet.java:244)
org.hudsonci.servlets.internal.ServletRegistrationFilterAdapter.init(ServletRegistrationFilterAdapter.java:96)
hudson.util.PluginServletFilter.init(PluginServletFilter.java:57)
io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:111)
org.wildfly.extension.undertow.security.RunAsLifecycleInterceptor.init(RunAsLifecycleInterceptor.java:85)
io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:97)
io.undertow.servlet.core.ManagedFilter.createFilter(ManagedFilter.java:79)
io.undertow.servlet.core.ManagedFilter.getFilter(ManagedFilter.java:65)
io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:81)
hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:47)
hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:139)
hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:73)
hudson.security.HudsonFilter.doFilter(HudsonFilter.java:156)
io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:70)
io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85)
io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61)
io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51)
io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45)
io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:63)
io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56)
io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70)
io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:261)
io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:247)
io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:76)
io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:166)
io.undertow.server.Connectors.executeRootHandler(Connectors.java:197)
io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:759)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)

-->

- Winston
Getting back on this track after a while.

I merged both commits and created a build. I also tested on two servers

GlassFish Server Open Source Edition 3.1.2.2   which I assume is EE 6

GlassFish Server Open Source Edition 4.1  which I assume is EE 7

Both seems to work fine. I will request our QA engineers to test on other servers (may be WildFly). 

http://www.oracle.com/technetwork/java/javaee/overview/compatibility-jsp-136984.html

Kaz, can you please tell us which server you tested, so we can create a matrix of tested servers.

- Winston

This one should resolve a bean name conflict (two beans named "default") that prevent Hudson from being deployed with Weld.

On Thu, Feb 19, 2015 at 7:12 AM, Winston Prakash <winston.prakash@xxxxxxxxx> wrote:
Hi Kaz,

Can you please give me the list of reviews (for Java EE 7 support) that are alive now. I saw you abandoning some. Just want to make sure I'm picking up the right ones.

- Winston

Hi Kaz,

In the community meeting we discussed about Hudson 3.3.0 release. The major theme of this release would be

- Java EE 7 support
- Moving Core to JDK 7 source API (dropping support for JDK 6 and below)
- Improving stability and performance

The development will continue until May with Release Candidate around last week of May, targeting the release around end of June, 2015. Few weeks are required to get the release approval from Eclipse Foundation.

Let us know if your work on Java EE 7 support can make it by then.

Thanks,

Winston

I learned unknown annotations are silently ignored if not available on the classpath as Stuart described, so we won't need to include any new jars.  It should be OK to just add dependency on cdi-api with scope 'provided' so that we can use CDI annotations only at compile-time.  I hope I can make a new patch in a few days.

2015/01/29 2:39 "Winston Prakash" <winston.prakash@xxxxxxxxx>:
Hi Kaz,

I have created this wiki page (just cut and paste some info from this e-mail). Can you please update it with all the findings and detail the solution we are going to use.

We have to get approval from Eclipse to add any new jar we bundle. So list the new jars that will be included in the war.

Thanks for all the work.

- Winston

Just FYI, I got an error from Weld even for org.hudsonci.service.internal.ServiceSupport.setHudson that it has unsatisfied dependency.  As you can see, class ServiceSupport has no annotations, just its method setHudson has @Inject.

Accoding to the CDI 1.1 spec, in the default 'annotated' bean discovery mode, ServiceSupport should not be discovered as a bean since it has no annotations.  So it appears that Weld is trying to process all @Inject annotations even for classes that have no bean defining annotations, as long as they have constructors without parameters, with which they are considered as managed beans.  It is unsolicited in my opinion, but it actually works as such.

If we try to resolve this issue without CDI compatibility, we will have to use Guice-equivalent of javax.inject.Inject, if any.


On Wed, Jan 28, 2015 at 9:38 AM, Kaz Nishimura <kazssym@xxxxxxxxx> wrote:

Thank you for the description.  I had believed annotations must be on the classpath if not provided by the container.

2015/01/28 9:26 "Stuart McCulloch" <mcculls@xxxxxxxxx>:

On Wednesday, 28 January 2015 at 00:22, Kaz Nishimura wrote:

If we ship Hudson with a cdi-api jar, compatibility with Java EE 5 servers will not be a problem, I believe.

I wouldn’t ship it with the cdi-api jar, instead make the dependency scope provided as the web container would be expected to provide it. That way the helper will activate on CDI capable web containers, and will be ignore elsewhere.

On the other hand, if we ship Hudson with the cdi-api 1.1 jar, does it break compatibility with Java EE 6?  I hope it doesn't but I am not a Java expert, so I chose to depend on the latest official release of CDI 1.0 API, cdi-api 1.0-SP4 for the moment.

FYI, as far as I know, any cdi-api jars just contain annotations (and necessary classes and interfaces, if any) without any CDI implementation.

2015/01/28 2:04 "Stuart McCulloch" <mcculls@xxxxxxxxx>:
On Tuesday, 27 January 2015 at 16:53, Winston Prakash wrote:
Hi Kaz/Sturat/Bob,

Let me try to re-iterate and understand the situation.

Hudson works in EE containers 5.x and below because there is no CDI. It also works in EE 6 because CDI is not enabled by default. However DI works in Hudson because Guice used in Hudson properly takes care of DI annotations (@Inject etc).

In EE7 CDI is enabled. Since CDI finds DI annotations in the code, it thinks it service is required. However, since it finds the wrong Injection Helpers (Specified as a Singleton), which is really meant for Guice, it throws error.

Three suggestions so far:

1. Add some dummy implementation for CDI Injection Helpers, so CDI will be happy, though it does nothing. But still Guice takes care of the  DI annotations

2. Change all javax.inject.Singleton to com.google.inject.Singleton. Since CDI will not understand this annotation, it will not try to incorrectly use the Injection Helpers and throw exception. However, Guice understands this annotation and works a normal.

3. Replace Guice with CDI for a cleaner core.

Option 3 is the cleaner solution and is the most difficult choice.

Option 1 satisfies CDI and everything works in EE 6 & 7. But now Hudson stops working in EE5 and below.
If the injection helpers in 1) only use CDI annotations then there’s no reason that won’t work in EE5, since the JVM will silently ignore annotations that aren’t on the classpath
Options 2 is not cleaner. Because  we will have some java.inject.* annotations and com.google.inject.Singleton. Also java.inject.Singleton will be totally forbidden. However Hudson will work on EE 5 and below as well 6 & 7.

For an interim solution, I'm kind of leaning towards option 2 because we will not be sidelining EE 5 below. Lots of App servers may be still be in EE5.

My above understand may be still wrong. If so please educate me :-)


- WInston

According to Oracle's definition, CDI (JSR 346) is a standard part of the Java EE 7: http://www.oracle.com/technetwork/java/javaee/tech/index-jsp-142185.html even with the web profile.

Weld is well known as the reference implementation of CDI and used by several products but another implementation that conforms to JSR 346 can also be used instead, if any.  Other DI-only implementation that can coexist with CDI may be OK as well.  To use CDI or other DI technology is what each application chooses but CDI 1.1 (or Weld only?) is too strict about unsatisfied CDI dependencies in my opinion.

So if an application chooses not to use CDI, it can either just satisfy CDI dependencies without real implementations as I am trying to do now OR instruct users to disable CDI at deployment-time.  I don't think runtime switching is a good idea.  It would make QA complicated and could make the application less reliable.

Also note that GlassFish includes both Weld and HK2 as far as I know.  Since HK2 requires its own annotations to activate it, they can coexist without conflicts, I think.  Do you know any Guice update (or its plan) regarding conflict avoidance?

I agree with Bob. One important difference we make in Hudson is, rather than supporting 1000's of plugins by keeping backward compatibilities with outdated technologies, we take bold steps to move to new technologies and try to keep the core more stable, scalable and modern. On the process we may keep only few 100s of most important plugins working better on the modern core. But that is sufficient  for enterprises with huge Hudson installation looking for a much stabler CI server.

Having said that, we have a bug existing for more than a year stating Hudson does not work when deployed to Glassfish 4.x. I'm wondering if this simple workaround is stable enough to include it in the next bugfix release and then take up the task of moving to the standard DI implementation.

Now comes the question, which is the standard DI ?

I have very limited knowledge of CDI. Based on my understanding (through limited reading)

CDI = DI + additional contexts. In Hudson we use only DI (Guice). There are three DI implementations (Guice, HK2, Spring). Weld which is a CDI reference implementation, has its own DI  (I think it is simplified spring DI)  and additional contexts.

Theoretically I would think the DI in CDI would be switchable (or play nicely with other DI). That means either you use the default DI in Weld or  plug in Guice/HK2 as DI. Looks like Glassfish 4.x is making HK2 work with CDI.

Do we need to have the full CDI (which is a superset) bundled in Hudson or use only the subset but standard DI in Hudson so that when we run on EE7 containers with CDI already in place, the bundled DI becomes "inactive" allowing the container CDI to take over (or am I just being ignorant here :-)  ).

So which one is the standard DI -- HK2, Guice, Spring, Weld DI?

- Winston

I think the future is upon is. My humble opinion is we need to find a CDI-compatible implementation that will work fine with Tomcat and Jetty (and I guess Glassfish for the diehards).

Editorial comment: Hudson can't continue to be a graveyard for old technologies.

Whatever we choose, thanks, Kaz, for digging into this!

On Fri, Jan 23, 2015 at 11:31 PM, Kaz Nishimura <kazssym@xxxxxxxxx> wrote:
It would be a future option to rely on CDI entirely, but Hudson currently uses Guice for dependency injection (as far as I know) and it actually works now, so such a switch will require some rewrites.  And CDI is not available on all Java web servers yet, for example, Tomcat and Jetty do not include it by default.

So I cannot tell whether such rewrites deserve to do or not.


On Sat, Jan 24, 2015 at 11:01 AM, Bob Foster <bobfoster@xxxxxxxxx> wrote:
Why not make it work with CDI by using CDI?

On Fri, Jan 23, 2015 at 5:50 PM, Kaz Nishimura <kazssym@xxxxxxxxx> wrote:
I submitted a patch to satisfy all unsatisfied dependencies only on the form as https://git.eclipse.org/r/#/c/40294/

The advantage of this approach would be it does not change any existing classes and all the producer methods are placed inside a small number of unused classes.  In addtion to this patch, a rename of the @Named annotation of ExtensionLocator actually allowed me to deploy Hudson 3.2.2-SNAPSHOT on GlassFish 4.1 without changing any deployment options.

It might better to change the package and class names, though.


On Sat, Jan 24, 2015 at 9:24 AM, Kaz Nishimura <kazssym@xxxxxxxxx> wrote:
As one of the first steps, I made classes like the following just to satisfy unsatisfied CDI dependencies, assuming these methods are never called:

@Singleton
public class InjectionHelper {

    @Produces
    private Injector getInjector() {
        return null;
    }

    @Produces
    private SmoothieContainer getSmoothieContainer() {
        return null;
    }

    @Produces
    @Named("default")
    private ExtensionLocator getDefaultExtensionLocator() {
        return null;
    }

    @Produces
    private List<ExtensionFinder> getExtensionFinders() {
        return null;
    }

    @Produces
    @Parameters
    private Map<String, String> getParametersMap() {
        return null;
    }
}

Each producer method might throw an UnsupportedException instead of just returning null to indicate more clearly that it shall not be used.  What do you think?

In addition, Bug 458002 must also be resolved to deploy Hudson on a Java EE 7 server with its default settings.


On Fri, Jan 23, 2015 at 5:59 PM, Kaz Nishimura <kazssym@xxxxxxxxx> wrote:
Oops, s/following test/following text/

On Fri, Jan 23, 2015 at 5:57 PM, Kaz Nishimura <kazssym@xxxxxxxxx> wrote:
As Winston suggested, I want to start discussion about Java EE 7 server support (or CDI 1.1 support) in Hudson.  The following test is my understanding of the current situation (mostly taken from my forum post).

(Basic assumption)
As far as I know, Hudson uses dependency injection based on Guice by Google and does not use CDI that is now a standard part of Java EE (6 and later).

(No problem before Java EE 7)
Java EE 6 included CDI 1.0 but it is not automatically enabled if beans.xml is not included, so Hudson is happy with any Java EE 6 servers.

(Problem with Java EE 7)
To resolve issues that many users forget to include beans.xml (I guess), CDI 1.1 introduced bean discovery modes and CDI is automatically enabled in the 'annotated' mode even if there is no beans.xml. At least one (and the reference) CDI implementation, Weld by JBoss, tries to discover a bean that can be injected to any method and field annotated with @Inject even if it will not actually use CDI for injection, which causes conflicts to the use of @Inject in Hudson.

(Workaround)
Most (or all) Java EE 7 servers has an option to disable the automatic CDI when deploying an application. By disabling the automatic CDI, Hudson can be deployed successfully on such servers. A problem is the way to activate the option differs by servers.

(No simple resolution)
Although CDI 1.1 introduced bean discovery modes and one of which is 'none', CDI 1.0 implementations will not see the value and might enable CDI
by the existence of beans.xml contrary to the intent to disable it. So including beans.xml is not an option to resolve this problem at all.


My proposal is to add some bean classes to Hudson that have producer methods solely for satisfying dependencies on the form.  I believe the producer methods need not to do anything useful since Hudson does not actually use CDI.  If those methods are known not to be called, they can just either return null or throw an exception always.






_______________________________________________
hudson-dev mailing list
hudson-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/hudson-dev



Back to the top