1 2 Previous Next 15 Replies Latest reply on Apr 1, 2010 3:37 AM by Glenn Silverman

    Scala + JSF 2.0 on Jboss 6 deployment error

    Glenn Silverman Newbie
      I've been trying to mix some scala code in with my Weld jsf-jee-minimal archetype project. My test case was to see if the JavaQuiz example in "Core Java ServerFaces, Third Edition" would work after rewriting the code as described in http://vikasrao.wordpress.com/2009/01/28/jsf-with-scala-managed-beans/, but making it work for JSF 2.0. I refactored QuizBean to conform to a more functional approach, but on deployment to JBoss 6, I get the following error:

      DEPLOYMENTS IN ERROR:
        ".../_WeldBootstrapBean" is in error due to the following reason(s): org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001400 Normal scoped bean org.jboss.weld.bean-flat-ManagedBean-class JavaQuizBean is not proxyable

      And here is my scala code:

      class Problem(@BeanProperty val question:String, @BeanProperty val answer:String) {
             
              def isCorrect(response:String):Boolean =
                      response.trim.equalsIgnoreCase(answer)
      }

      @Named
      @SessionScoped
      class JavaQuizBean extends Serializable{
              var currentProblem:Int = 0
              var tries:Int = 0
              @BeanProperty var score:Int = 0
              @BeanProperty var response:String = ""
          @BeanProperty var problem:Problem = _
         
          val p1 = new Problem("What trademarked slogan describes Java Development? Write once,...","run anywhere")
              val p2 = new Problem("What are the first 4 bytes of every class file(in hexadecimal)?", "CAFEBABE")
              val p3 = new Problem("What does this statement print? System.out.println(1+\"2\");", "12")
             
              val problems:Array[Problem] = Array(p1,p2,p3)
             
              problem = problems(currentProblem)
             
              def QuizBean(){ startOver()}
             
              def startOver(){
                      currentProblem = 0
                      problem = problems(currentProblem)
                      score = 0
                      tries = 0
                      response = ""
              }
                     
              def nextProblem(){
                      currentProblem = currentProblem + 1
                      problem = problems(currentProblem)
                      tries = 0
                      response = ""
              }
             
              def answerAction():String = {
                      tries = tries + 1
                      def anotherTry:Boolean = if(tries < 2) true else false
                     
                      def isDone:Boolean = currentProblem == problems.length-1
                      //case class Answer(correct:Boolean, goOn:Boolean, done:Boolean)               
                     
                      def myAnswer:String = (problem.isCorrect(response), anotherTry, isDone) match{
                              case (true,_,true) => {
                                      score = score + 1
                                      return "done"
                                      }
                              case (false,_,true) => return "done"
                              case (false,true,_) => {
                                      response = ""
                                      return "again"                         
                              }
                              case (false,false,_) => {
                                      nextProblem
                                      return "failure"
                              }
                              case (true,true,false) =>{
                                      score = score + 1
                                      nextProblem
                                      return "success"
                                      }
                      }
                     
                      myAnswer
                             
                             
              }
             
              def startOverAction():String = {
                      startOver()
                      "startOver"
              }
      }


      What makes this code not "proxyable"?




        • 1. Re: Scala + JSF 2.0 on Jboss 6 deployment error
          Glenn Silverman Newbie

          Found out the problem. My code uses final values (in Scala tuples), which can't be extended (proxied). I initially tried using case classes, which are also final, so not proxyable. So it seems some, if not most, of scala constructs are off-limits when it comes to implementing JSF 2.0 managed beans. Bummer.


          Glenn

          • 2. Re: Scala + JSF 2.0 on Jboss 6 deployment error
            Nicklas Karlsson Master

            Next release of Weld will actually tell you what is wrong in more detail ;-)

            • 3. Re: Scala + JSF 2.0 on Jboss 6 deployment error
              Glenn Silverman Newbie

              I've written to the Scala users forum on this as well. The problem seems to be that JBoss 6, or any Java EE compliant server running JSF 2.0, can't proxy Scala's match...case construct in a managed bean. Since this constuct is such an important one in Scala (I can't imagine writing any meaningful code without it), shouldn't this be fixed?


              Glenn

              • 4. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                Nicklas Karlsson Master

                Checked if there are any JIRAs for it? I vaguely recall something about Scala before..

                • 5. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                  Glenn Silverman Newbie

                  There is a discussion of Web Beans and Scala which places the blame on Seam. But, I'm not using Seam (at least not that I know of), and I tried using match..case in the embedded Glassfish server, and it failed as well as being not proxyable. The proximate cause is listed as a error at


                  org.jboss.weld.Validator.validateBean(Validator.java:85).


                  So maybe this ia a more generic problem with CDI.


                  Glenn


                  • 6. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                    Dan Allen Master

                    Glenn Silverman wrote on Mar 30, 2010 23:32:


                    There is a discussion of Web Beans and Scala which places the blame on Seam. But, I'm not using Seam (at least not that I know of), and I tried using match..case in the embedded Glassfish server, and it failed as well as being not proxyable. The proximate cause is listed as a error at

                    org.jboss.weld.Validator.validateBean(Validator.java:85).

                    So maybe this ia a more generic problem with CDI.

                    Glenn




                    Can you do two things.


                    First, remove the @ManagedProperty annotations because those are JSF managed bean annotations that don't belong in a CDI bean.


                    Second, could you trim down the bean until it works, then figure out the last thing you took out, put it back in and post that simplified bean? We are looking for the simplest possible bean that doesn't work. It will make it a lot easier for people to get a picture of what exactly is causing the problem.

                    • 7. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                      Glenn Silverman Newbie
                      First of all, I'm not using @ManagedProperty, but @Named, so it already is a CDI bean. I took your challenge and went through all the permutations I could think of and found that the following bean will not deploy in Jboss 6 nor in Glassfish (I used the weld-jsf-jee-minimal archetype to build and deploy):

                      @Named
                      @SessionScoped
                      class myBean extends Serializable{
                           var tries:Int = 0
                           
                           def myAction():String = {
                                tries = tries + 1
                                
                                def testThis:String = (1,0,0) match {
                                     case (1,_,_) => "one"
                                     case (_,2,_) => "two"
                                     case (_,_,3) => "three"
                                }
                                
                                "done"
                           }     

                      }

                      The following points seem to apply:
                      1)If you remove @SessionScoped, the bean will deploy
                      2)The match...case structure doesn't matter, only that one be there.
                      3)Change def testThis to val testThis and the bean will deploy.
                      4)The relevant point seems to be that your bean has a var that you modify in a method that contains another method with a match...case construct.

                      Other than that, I can't isolate the problem further. I'm hoping someone more knowledgeable than I can figure this out. One thing, though, match...case by itself does not seem to be the issue, and that's good, I suppose.

                      Glenn


                      • 8. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                        Shane Bryzak Master

                        It's probably just a typo, but your class should implements Serializable, not extends it (you should actually get a compiler error the way it's written now).

                        • 9. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                          Dan Allen Master

                          Thanks Glenn. That should definitely help maximize the chance of us getting to the bottom of this issue.



                          First of all, I'm not using @ManagedProperty, but @Named, so it already is a CDI bean.


                          I was just giving you a hard time ;) Those JSF annotations just get to me sometimes.



                          The following points seem to apply:
                          1)If you remove @SessionScoped, the bean will deploy


                          Clearly identifying that this is a proxy problem, since @Dependent beans aren't proxied in Weld.



                          2)The match...case structure doesn't matter, only that one be there.
                          3)Change def testThis to val testThis and the bean will deploy.
                          4)The relevant point seems to be that your bean has a var that you modify in a method that contains another method with a match...case construct.


                          Curious how specific that is. It would be interesting to see if the same issue happens in OpenWebBeans, just as another thing to experiment with...because this is likely (without diving into it yet) a limitation of the proxy library, which in our case is Javassist.



                          Other than that, I can't isolate the problem further. I'm hoping someone more knowledgeable than I can figure this out. One thing, though, match...case by itself does not seem to be the issue, and that's good, I suppose.


                          You've certainly got a nice concise example to pass around now ;)

                          • 10. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                            Shane Bryzak Master

                            Shane Bryzak wrote on Mar 31, 2010 03:37:


                            It's probably just a typo, but your class should implements Serializable, not extends it (you should actually get a compiler error the way it's written now).


                            Oops, I just realized your code listing was Scala.. just ignore me.

                            • 11. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                              Glenn Silverman Newbie
                              Here's a simple step-by-step test anyone can try to generate a non proxyable error message in either JBoss 6 or Glassfish.

                                 1. Create a project with the weld-jsf-jee-minimal maven archetype
                                 2. Add the maven-scala-plugin and scala-library dependency to the pom (see [scala-tools.org] for details)
                                 3. Create a Scala class file in your src directory with the contents shown (myBean)
                                 4. Run in glassfiish with the command mvn: package embedded-glassfish:run

                              import scala._
                              import java.io.Serializable
                              import javax.inject.Named
                              import javax.enterprise.context.SessionScoped

                              @Named
                              @SessionScoped
                              class myBean extends Serializable{
                              var tries:Int = 0
                                 def myAction():String = {
                                tries = tries + 1
                                   def testThis:String = (1,0,0) match {
                                 case (1,_,_) => "one"
                                 case (_,2,_) => "two"
                                 case (_,_,3) => "three"
                                }
                                   "done"
                              }

                              }

                              Glenn
                              • 12. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                                Marius Bogoevici Newbie

                                Glenn,


                                essentially, this compiles to:




                                public class myBean extends java.lang.Object implements java.io.Serializable,scala.ScalaObject{
                                    private int tries;
                                    public myBean();
                                    private final java.lang.String testThis$1();
                                    public java.lang.String myAction();
                                    public void tries_$eq(int);
                                    public int tries();
                                }





                                Now, this comes in direct violation of the spec, which requires that normal scoped to be proxyable, therefore they cannot have final methods. So, unless scala can fine tune the way the class file is generated, this might be an issue.


                                But generally speaking, I wonder if it wouldn't be possible for future versions of the spec to actually relax the condition, by excluding private methods from the ban (since they cannot be extended/proxied/invoked by a client anyway).


                                Marius

                                • 13. Re: Scala + JSF 2.0 on Jboss 6 deployment error
                                  Dan Allen Master

                                  Glenn,


                                  You can track the discussion that Marius initiated on the weld-dev mailinglist: [weld-dev] Proxyability of private methods

                                  1 2 Previous Next