4 Replies Latest reply on Mar 17, 2016 3:14 PM by gberish

    Why is Wildfly looking for a version of my Class ending in a $?

    gberish

      I have a MDB deployed in and ear package on WildFly Full 9.0.2.Final.

       

      In  onMessage() I have this line of code:

      Integer sessionType = SessionValuesTK.getSessionForAction (actionType);

       

      It throws this to the server log:
        ...

        at java.lang.Thread.run(Thread.java:745)

      Caused by: java.lang.NoClassDefFoundError: org/america3/gotest/server/interfaces/SessionValues$1

        at org.america3.gotest.server.messaging.GoMsgBean.delegateToSession(GoMsgBean.java:301)

        at org.america3.gotest.server.messaging.GoMsgBean.onMessage(GoMsgBean.java:169)

        ... more

      Caused by: java.lang.ClassNotFoundException: org.america3.gotest.server.interfaces.SessionValues$1 from [Module "deployment.GoTest.ear.GoTest.jar:main

      " from Service Module Loader]

        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:205)

                                    ... more

      Everything I read suggests its because my code has an Enum or inner class somewhere, but I don't.


      Here's the Class and the interface it implements that go with that line:


      Notes:

      I pasted the whole Class and Interface code since I couldn't find a way to get a simple example that threw that Exception. The static final int values are int, because I use them an a switch() method and they don't like Integers. BUT ... I took that switch() out when I got the above error.


      I no longer think it was such a great idea to create a separate Class to hold the method used to look up Interface variables, and I'd welcome code criticism, BUT ... I right now I'm fixated on why the heck WildFly keeps looking for SessionValues$1.


      GoTest.ear definitely contains GoTest.jar, and the jar definitely contains

      org.america3.gotest.server.interfaces.SessionValues, and

      org.america3.gotest.server.interfaces.SessionValueTK.

      Just no SessionValues$1!


      THE CLASS that holds the static method:

        package org.america3.gotest.server.interfaces;

        public class SessionValuesTK implements SessionValues{

          //Method that seems to throw the Exception.

          static public Integer getSessionForAction (Integer actionType) {

        if (actionType == null || !ACTION_SESSION_MAP.keySet().contains(actionType)) {

          return BAD_SESSION_TYPE;

        }

          return ACTION_SESSION_MAP.get(actionType);

        }

      }

       

      THE INTERFACE:

        package org.america3.gotest.server.interfaces;

        public interface SessionValues {

       

          static public Integer getTestedSessionType (Integer sessionType) {

            if (sessionType == null ||

              sessionType.equals (BAD_SESSION_TYPE) ||

              !SESSION_NAMES.keySet().contains (sessionType)) {

              return BAD_SESSION_TYPE;

            } else {

              return sessionType;

            }

          }


      static public final int BASE = 6579;

      static public final int BAD_SESSION_TYPE = 1 + BASE;

      static public final int LOGGER           = 1 + BAD_SESSION_TYPE;

      static public final int ENROLLER         = 1 + LOGGER;

      static public final int FILER            = 1 + ENROLLER;

      static public final int PLAYER           = 1 + FILER;

      static public final int TESTER           = 1 + PLAYER;

       

          static public final HashMap<Integer, String> SESSION_NAMES = new HashMap<Integer, String> () {

            public static final long serialVersionUID = 1L;

            { put (BAD_SESSION_TYPE, "Bad Session Type");

              put (LOGGER, "Logger");

              put (ENROLLER, "Enroller");

              put (FILER, "Filer");

              put (PLAYER, "Player");}

          };

       

          // Map Action type to Session type

      static public final HashMap<Integer, Integer> ACTION_SESSION_MAP = new HashMap<Integer, Integer> () {

        public static final long serialVersionUID = 1L;

        { put (ActionValues.GAME_DELETE, FILER);

          put (ActionValues.ENROLL, ENROLLER);

          put (ActionValues.EXIT, LOGGER);

          put (ActionValues.GAME_LOAD, FILER);

          put (ActionValues.LOG_OUT, LOGGER);

          put (ActionValues.LOG_IN, LOGGER);

          put (ActionValues.GAME_LOAD, FILER);

          put (ActionValues.NOTIFY_SERVER_NEW_STONE, PLAYER);

          put (ActionValues.NOTIFY_SERVER_NEW_PASS, PLAYER);     

          put (ActionValues.GAME_FETCH, FILER);

          put (ActionValues.GAME_GET_DELETE_LIST, FILER);

          put (ActionValues.GAME_GET_LOAD_LIST, FILER);

          put (ActionValues.GAME_SAVE_AS, FILER);}

        };

      }

        • 1. Re: Why is Wildfly looking for a version of my Class ending in a $?
          jaikiran

           

          THE INTERFACE:

            package org.america3.gotest.server.interfaces;

            public interface SessionValues {

           

              ...


          static public final int BASE = 6579;

          static public final int BAD_SESSION_TYPE = 1 + BASE;

          static public final int LOGGER           = 1 + BAD_SESSION_TYPE;

          static public final int ENROLLER         = 1 + LOGGER;

          static public final int FILER            = 1 + ENROLLER;

          static public final int PLAYER           = 1 + FILER;

          static public final int TESTER           = 1 + PLAYER;

           

              static public final HashMap<Integer, String> SESSION_NAMES = new HashMap<Integer, String> () {

                public static final long serialVersionUID = 1L;

                { put (BAD_SESSION_TYPE, "Bad Session Type");

                  put (LOGGER, "Logger");

                  put (ENROLLER, "Enroller");

                  put (FILER, "Filer");

                  put (PLAYER, "Player");}

              };

           

              // Map Action type to Session type

          static public final HashMap<Integer, Integer> ACTION_SESSION_MAP = new HashMap<Integer, Integer> () {

            public static final long serialVersionUID = 1L;

            { put (ActionValues.GAME_DELETE, FILER);

              put (ActionValues.ENROLL, ENROLLER);

              put (ActionValues.EXIT, LOGGER);

              put (ActionValues.GAME_LOAD, FILER);

              put (ActionValues.LOG_OUT, LOGGER);

              put (ActionValues.LOG_IN, LOGGER);

              put (ActionValues.GAME_LOAD, FILER);

              put (ActionValues.NOTIFY_SERVER_NEW_STONE, PLAYER);

              put (ActionValues.NOTIFY_SERVER_NEW_PASS, PLAYER);     

              put (ActionValues.GAME_FETCH, FILER);

              put (ActionValues.GAME_GET_DELETE_LIST, FILER);

              put (ActionValues.GAME_GET_LOAD_LIST, FILER);

              put (ActionValues.GAME_SAVE_AS, FILER);}

            };

          }

           

           

          It's those "object initialization" blocks of the (anonymous) class of type HashMap that are causing a problem. The object initialization blocks are run before the no-arg constructor of any class, so I am pretty sure that a call to put is going to cause problems and in fact is resulting in that NoClassDefFoundError.

          • 2. Re: Why is Wildfly looking for a version of my Class ending in a $?
            jaikiran

            jaikiran wrote:

            It's those "object initialization" blocks of the (anonymous) class of type HashMap that are causing a problem.

            By the way, that's what the $1 corresponds to in this example - that anonymous class you have in there.

            • 3. Re: Why is Wildfly looking for a version of my Class ending in a $?
              jaikiran

              FWIW, I would expect this to be reproducible in a simple standalone Java program too without WildFly in picture.

              • 4. Re: Why is Wildfly looking for a version of my Class ending in a $?
                gberish

                That's my problem.  I have no idea what Jboss thinks SessionValues$1 is.

                 

                But based on your comment, I guess JBoss sees the way in which my Interface declares a static final HashMap, and then populates it with other static final variables declared and defined in the Interface as an anonymous Class ...  but I have no clue why that should upset JBoss.  I use that technique in a lot of Interfaces.  And all of them, including the SessionValues Interface, work fine on the client side.

                 

                I guess I could try combining SessionValues and SessionValuesTK into a single regular Class and import it into all my SessionBeans.  Or maybe just get rid of the static, since all the values are final anyway.

                 

                If either works I'll post a note. 

                 

                NOTE:  I truncated the code before it got to using SessionValuesTK's method at all, and just printed a value obtained from a HashMap above with a hard coded key.  Even that threw same Exception.  So it has to be the way I'm populating the HashMaps.

                 

                AND:

                As I alluded to above, I'm not at all sure my approach makes any sense anymore.  The problem is my MessageDrivenBean, and all my SessionBeans, need the static final variables and associated HashMap carried by the SessionValues Interface, and an interface seemed a good way to do it.