6 Replies Latest reply: Apr 13, 2012 2:33 PM by Dan Allen RSS

[Solder 3.1.0.Final][Seam Validation 3.1.0.Final] and [Glassfish-embedded-all 3.1.2-b16]

blep Newbie

Hi,

 

I try to build a test case with Seam Validation, Arquillian and GF embedded but I'm facing a problem :

 

Caused by: java.lang.IllegalAccessError: tried to access class org.jboss.solder.servlet.event.ImplicitServletObjectsHolder$InternalServletContextEvent from class org.jboss.solder.servlet.event.ImplicitServletObjectsHolder$Proxy$_$$_WeldClientProxy

 

Full stack trace is available on http://pastebin.com/iWfhTqbg .

 

It looks similar to the problem ( http://java.net/jira/browse/GLASSFISH-14808 ) mentionned in the "supported platforms" paragraph in Solder, but the affected GF release is 3.1 (fixed in b47) and I use 3.1.2.

 

Could you confirm please the two issues are related ?

 

If no, is there any way to make Seam Validation work with GF embedded?

 

The code for the test case is:

 

@RunWith(Arquillian.class)
public class ValidationIT {


          @Deployment
          public static Archive<?> createTestArchive() {
                    MavenDependencyResolver resolver = DependencyResolvers.use(MavenDependencyResolver.class)
                                        .configureFrom(System.getenv("M2_HOME") + "/conf/settings.xml")
                                        .loadMetadataFromPom("pom.xml");
                    WebArchive archive = ShrinkWrap
                                        .create(WebArchive.class, "test.war")
                                        .addAsLibraries(resolver.artifacts("org.jboss.seam.validation:seam-validation-api").resolveAsFiles())
                                        .addAsLibraries(resolver.artifacts("org.jboss.seam.validation:seam-validation").resolveAsFiles())
//                                        .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
                                        .addAsManifestResource("META-INF/beans-validation.xml","beans.xml")
                                                            ;
                    return archive;
          }


          @AutoValidating
          public static class ValidatedService {
                    public String method(@NotNull String param) {
                              return "yes";
                    }
          }


          @Inject
          private ValidatedService validatedService;


          @Test
          public void testValidatedService() {
                    validatedService.method(null);
                    fail();


          }
}

 

 

  • 1. Re: [Solder 3.1.0.Final][Seam Validation 3.1.0.Final] and [Glassfish-embedded-all 3.1.2-b16]
    Jason Porter Master

    No clue what's going on there, the stack trace doesn't seem to help much. Have you searched the forums? There have been other GF embedded quesitons.

  • 2. Re: [Solder 3.1.0.Final][Seam Validation 3.1.0.Final] and [Glassfish-embedded-all 3.1.2-b16]
    heapifyman heapifyman Newbie

    Hi.

     

    Are there any news on this issue? I'm getting the same exception as blep when running my arquillian test in embedded glassfish 3.1.2. But I'm not using Seam Validation, just Seam Logging.

  • 3. Re: [Solder 3.1.0.Final][Seam Validation 3.1.0.Final] and [Glassfish-embedded-all 3.1.2-b16]
    Dan Allen Master

    I managed to get the test working, though I used a different container adapter. I'll explain the reason for the switch, then how I got the test working.

     

    The danger of embedded containers

     

    In the Arquillian project, we're all about real tests. There's a good reason for this philosophy. If you use mocks or a substitute container when testing code that uses a programming model (i.e., CDI), all you can be sure of is that you've faked out enough functionality to get the test to work. You can't be certain that your code really, truly works.

     

    Obviously, we provide adapters for embedded containers (i.e., substitute containers). The reason is, they often do a decent enough job of simultating the real environment when we are working in development that we are willing to make the trade-off for it's variations. I would expect, though, that you are running the same tests in CI using a real container...just to get that peace of mind.

     

    How do you know when not to use an embedded container?

     

    If you write a test and you are positive it should work, but instead it throws some wacky exception, immediately stop and try the same test in a real container. In your case, I would advise running this test on managed or remote GlassFish, for instance. Both of those adapters use an authentic GlassFish instance. If the test passes, then you have answered the question of this section.

     

    When the embedded container begins to act inconsistently, drop it.

     

    As with all things, there are exceptions to the rule. If the code really *should* work on the embedded container, then it may be worth exploring why it isn't. That may lead you to the discovery of a bug in the library. If debugging the library is your main concern, chase it down. If you are just trying to get a test written for your application code, stop using the embedded container (or save debugging it for a rainy day).

     

    Getting a green bar for this test

     

    The first thing I did was move ValidationService into it's own file. Then you'll see it's clear you need to package it in the ShrinkWrap archive.

     

    package org.arquillian.example;
    
    import javax.validation.constraints.NotNull; 
    import org.jboss.seam.validation.AutoValidating;
    
    @AutoValidating
    public class ValidatedService {
        public String method(@NotNull String param) {
            return "yes";
        }
    }
    

     

    Next, I made some updates to the test. Here's what I changed:

     

    • Add beans.xml to WEB-INF (not META-INF)
    • Use try/catch to handle the expected exception (otherwise you get serialization problems w/ the exception class)
    • Moved beans-validation.xml to the src/test/resources root
    • Disabled the configureFrom() (you don't have to change this...I just put the repositories in my pom.xml to simplify things)

     

    package org.arquillian.example;
    
    import javax.inject.Inject;
    import org.hibernate.validator.method.MethodConstraintViolationException;
    import org.jboss.arquillian.container.test.api.Deployment;
    import org.jboss.arquillian.junit.Arquillian;
    import org.jboss.shrinkwrap.api.Archive;
    import org.jboss.shrinkwrap.api.ShrinkWrap;
    import org.jboss.shrinkwrap.api.spec.WebArchive;
    import org.jboss.shrinkwrap.resolver.api.DependencyResolvers;
    import org.jboss.shrinkwrap.resolver.api.maven.MavenDependencyResolver;
    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    
    @RunWith(Arquillian.class)
    public class ValidationIT {
    
        @Deployment
        public static Archive<?> createTestArchive() {
            MavenDependencyResolver resolver = DependencyResolvers.use(MavenDependencyResolver.class)
                    .loadMetadataFromPom("pom.xml");
            WebArchive archive = ShrinkWrap.create(WebArchive.class, "test.war")
                    .addClasses(ValidatedService.class, ValidationIT.class)
                    .addAsLibraries(resolver.artifacts("org.jboss.seam.validation:seam-validation-api").resolveAsFiles())
                    .addAsLibraries(resolver.artifacts("org.jboss.seam.validation:seam-validation").resolveAsFiles())
                    .addAsWebInfResource("beans-validation.xml", "beans.xml");
            return archive;
        }
    
        @Inject
        private ValidatedService validatedService;
    
        @Test
        public void testValidatedService() {
            try {
                validatedService.method(null);
                Assert.fail();
            }
            catch (MethodConstraintViolationException e) {
                // expected
            }
        }
    }
    

     

    Next, I added a profile for the GlassFish remote container adapter in my pom.xml.

     

            <profile>
                <id>arquillian-glassfish-remote</id>
                <dependencies>
                    <dependency>
                        <groupId>org.jboss.spec</groupId>
                        <artifactId>jboss-javaee-6.0</artifactId>
                        <version>1.0.0.Final</version>
                        <type>pom</type>
                        <scope>provided</scope>
                    </dependency>
                    <dependency>
                        <groupId>org.jboss.arquillian.container</groupId>
                        <artifactId>arquillian-glassfish-remote-3.1</artifactId>
                        <version>1.0.0.CR3</version>
                        <scope>test</scope>
                    </dependency>
                </dependencies>
            </profile>
    

     

    I then enabled the arquillian-glassfish-remote profile in Eclipse.

     

    Next, I downloaded GlassFish 3.1.2 and extracted it. I setup the container in Eclipse so I could start it from there. Of course you could just start it from the commandline...but then debugging is more difficult.

     

    With GlassFish running and the arquillian-glassfish-remote profile enabled:

     

    Run As > JUnit Test

    Green bar

     

    Closing thoughts

     

    Code that uses Solder works fine on GlassFish 3.1.2, but it does not play very nicely with Embedded GlassFish. It's just a hostile environment for CDI because of visibility issues that come with starting an embedded container inside an existing Java process. You end up in a minefield of class visibility and access problems.

     

    If you want the container to start automatically just like embedded, then switch to the arquillian-glassfish-managed-3.1 container. It works almost exactly the same as the remote container, except that Arquillian will start the standalone process at the beginning of the test execution and stop it at the end. In other words,

     

    managed >>>> embedded

     

    But for speed of development:

     

    remote > managed

     

    since you don't have to wait for the container to start...and you can start it in debug mode very easily and keep it there.

     

    Keep that in mind.

  • 4. Re: [Solder 3.1.0.Final][Seam Validation 3.1.0.Final] and [Glassfish-embedded-all 3.1.2-b16]
    Dan Allen Master

    Btw, there is one major issue with Solder running on Embedded GlassFish.

     

    There are hacks to load special extensions for when using certain versions of Weld in GlassFish. There's only one problem with this approach. Embedded GlassFish does not allow you do see the package manifest info. It has to do with OSGi visibility rules. Therefore, the following code in TypedMessageBundleAndLoggerExtension.java throws a NullPointerException.

     

    processTypesInModule = System.getProperty("glassfish.version") != null && cdi.getImplementationTitle().contains("Weld")
                    && cdi.getImplementationVersion().equals("20110114-1644");
    

     

    I don't know what we need to do to get the Weld version in this environment. Perhaps it would be best to ask the GlassFish developers.

     

    If nothing else, this code needs to be changed to perform a null check on getImplementationTitle() and getImplementationVersion(). We shouldn't just skip this extension if this information is not available.

  • 5. Re: [Solder 3.1.0.Final][Seam Validation 3.1.0.Final] and [Glassfish-embedded-all 3.1.2-b16]
    heapifyman heapifyman Newbie

    Thanks for the detailed explanation. If I understand correctly your message is: don't use an embedded container.

    I'll try to keep that in mind.

    Thanks again.

  • 6. Re: [Solder 3.1.0.Final][Seam Validation 3.1.0.Final] and [Glassfish-embedded-all 3.1.2-b16]
    Dan Allen Master

    Thanks for the detailed explanation. If I understand correctly your message is: don't use an embedded container.

     

    Consider it more as advice, not as a directive. You may have a good reason for using an embedded container, and it may work for what you are trying to do. You know best what is right for you. I'm just saying that if the embedded container is giving you problems, you need to remember that embedded containers have quirks. It's the nature of the beast. If they become more trouble than they are worth, I encourage you to recognize that it's the embedded container that is at fault and you should explore alternatives for the sake of productivity.

     

    In other words, just be skeptical about embedded containers Try them, use them, but with care and observation.