11 Replies Latest reply on Apr 29, 2004 4:04 AM by darranl

    JNDI and NotSerializableException

    astrien

      Here's the thing:
      I've got a very nicely coded WAR file that starts life with a bootstrap class (extending ServletContextListener). Within that class, one of the first things I try to do is to bind() some tidbits to the InitialContext. This is where the fun starts.

      In the interest of not pissing off Adrian (God of the Boards), I have done much research into this and have found the following by compiling bits from the Resin boards, Google, the forums here, and rips in the space-time continuum.

      What I've found is that (I think), in the jndi.properties file, I have the following:

      # DO NOT EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING
      #
      java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
      java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
      java.naming.provider.url=localhost:1099


      This causes all of the calls to JNDI, be it bind()s or lookup()s, to be forced through on port 1099, which requires anything you are trying to bind() or lookup() to be Serializable.

      All I'm trying to do here is to get the nice, normal, local JNDI context from within classes running in my WAR and use them internally. I am not trying to access JNDI externally (yet).

      What is stumping me is how to get the normal JNDI context that I know and love, with local memory hashes and all, that does not require me to implement Serializable on everything I want to pass through it.

      The code I am using is as follows:

      To get the InitialContext
       this.vInitCtx = new InitialContext();
      


      To bind something to the context where name=String and target=Object
       try {
       this.vInitCtx.bind(name,target);
       } catch(NamingException nEx) {
       String msg = "JNDIHelper could not bind target object to name '"+name+"'";
       this.logger.severe(msg);
       this.logger.severe("-- "+nEx.getExplanation());
       this.logger.severe("-- "+nEx.getMessage());
       throw new Exception(msg,nEx);
       }
      


      As far as I can tell, when the thread hits the bind() method, I am getting a NamingException, which is wrapped around a CommunicationException, and that has as it's root a NotSerializableException.

      So who's the first to tell me that I missed a period somewhere?

        • 1. Re: JNDI and NotSerializableException
          darranl

          Please tell me that you are joking.

          Why have you edited the jndi.properties file.

          # DO NOT EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING

          • 2. Re: JNDI and NotSerializableException
            darranl

            Additionaly the phrase 'DO NOT EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING' can be interpreted as :-

            This file MUST NEVER be changed by JBoss users.

            or

            Changing this file will break JBoss.



            • 3. Re: JNDI and NotSerializableException
              astrien

              First up, calm down!

              Second, did I say that I had edited the file? No. I'm not a newbie, and I know when a developer puts a warning like that in the file, that he does so for a reason.

              This is the way I found the file:

              # DO NOT EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING
              #
              java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
              java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
              


              I later edited it after seeing a great many posts that have 3 settings instead of 2, resulting in this:

              # DO NOT EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING
              #
              java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
              java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
              java.naming.provider.url=jnp://localhost:1099
              


              I played with several variations of the java.naming.provider.url, thinking that maybe there was some sort of cock-up with used ports on my machine, but after a few rounds of that, along with monotoring netstat and ipconfig commands on my dev machine, I figured that the problem was somewhere else, and since I was left with no more leads, I posted here.

              Now unless you have something more constructive to offer, I expect I won't hear from you again. I understand that the ratio of newbie to expert postings here can bring a tear to a developer's eye, but being rude right off without asking me first if I'd tried running with the default config doesn't help anyone. Not me with this problem, and not you with your image.

              To head off any other flipouts, I looked at the jboss-service.xml file as well, but never touched it. The entry in there for JNDI currently reads as follows:
               <!-- ==================================================================== -->
               <!-- JNDI -->
               <!-- ==================================================================== -->
              
               <mbean code="org.jboss.naming.NamingService"
               name="jboss:service=Naming">
               <!-- The listening port for the bootstrap JNP service. Set this to -1
               to run the NamingService without the JNP invoker listening port.
               -->
               <attribute name="Port">1099</attribute>
               <!-- The bootstrap JNP server bind address. This also sets the default
               RMI service bind address. Empty == all addresses
               -->
               <attribute name="BindAddress">${jboss.bind.address}</attribute>
               <!-- The port of the RMI naming service, 0 == anonymous -->
               <attribute name="RmiPort">1098</attribute>
               <!-- The RMI service bind address. Empty == all addresses
               -->
               <attribute name="RmiBindAddress">${jboss.bind.address}</attribute>
               </mbean>
              
               <mbean code="org.jboss.naming.JNDIView"
               name="jboss:service=JNDIView"
               xmbean-dd="resource:xmdesc/JNDIView-xmbean.xml">
               </mbean>
              


              • 4. Re: JNDI and NotSerializableException
                darranl

                Ok, restore the file to it's original settings - it should not be changed.

                The posts you have seen are incorrect, the comment was added to the top of the file to stop people changing it.

                • 5. Re: JNDI and NotSerializableException
                  darranl

                  Also what is the actual stack trace that you are getting?

                  • 6. Re: JNDI and NotSerializableException
                    darranl

                    Looking at the JNDI code of JBoss, any object bound to JNDI will be stored in a serialized form anyway.

                    For this reason except in a couple of situations it is a requirement of the JBoss JNDI implementation that objects bound to JNDI are serializable.

                    If you access JNDI from the same JVM as the JNDI server you might be returned the actual object that was bound to JNDI.

                    In other situations you would be returned the serialized version that would be deserialized.

                    If your objects implemented the 'javax.naming.Referenceable' interface that might be a solution to your problem.

                    • 7. Re: JNDI and NotSerializableException
                      astrien

                      I can't give you a stack trace, because as you see above, I am forced to handle the exception. Since JBoss is handling all the logging output, there's no way for me to get the output of printStackTrace().

                      What I am getting in JBuilder's debug mode, is that the NotSerializableException is originating from java.util.logging.Logger. Now, considering that I am trying to store my Bootstap object in the JNDI, and that Bootstrap, being a ServletContextListener, extends HttpServlet which itself implements Serializable, what you are saying is that storing it should not be a problem. Except... I am using java.util.logging.Logger to log error messages in that class, and Logger isn't serializable at all.

                      So there I go. I'll have to declare the data member that holds Logger as transient and then handle the reconstitution of the Logger member in the readObject() method - or use Referenceable for the first time. There's always something new to learn in the JDK... :)

                      Now here's a good question. Is it just JBoss's implementation of the Naming packages that requires objects be Serializable? I swear that requirement is never mentioned in the JDK javadocs and I've never come up against it before.

                      • 8. Re: JNDI and NotSerializableException
                        darranl

                        I did quite a bit of research on JNDI a while a go and from what I can remember in the specification the JNDI implementation can decide the requirements on the objects being bound.

                        An example where serializable could be enforced would be if JNDI was being used to persist objects to a filesystem. If the JNDI specification forced the implementation to accept non-serializable objects a JNDI implementation would not be useable in this way.

                        I don't think that the JBoss documents really cover what can and can't be stored in JNDI.

                        There is also a JBoss specific way to store non-serializable objects in the JBoss JNDI using a JBoss specific wrapper class but I can't remember which one it was and additionaly you probably wouldn't want to use it as it would make your app run on JBoss only.

                        With regards to obtaining stack traces although not a good practice in the final version of your application you can invoke the printStackTrace() method on the Exception that you have caught and if you are using the default log4j.xml configuration the stack trace should be displayed on the JBoss console.

                        • 9. Re: JNDI and NotSerializableException
                          astrien

                          Well, here's a quote from a nice article at JavaWorld that I just found:

                          According to the JNDI specification, service providers are encouraged (but not required) to support object storage in one of the following formats:

                          * Serialized data
                          * Reference
                          * Attributes in a directory context

                          Here's the article for anyone interested:

                          http://www.javaworld.com/javaworld/jw-03-2000/jw-03-howto.html

                          Just a thought - I'm pretty sure that JBoss isn't serializing the JMS queues it stores in JNDI, so the queues must be using something (like that JBoss interface you mentioned) to get around that requirement.

                          Anyhoo - thanks for your help. I managed to get past that bind() line by making the Logger variable transient, so all is well again. I may factor out the functionality I need in Bootstrap into utility classes that can be serialized with no worry of BAD THINGS happening. Take care...

                          • 10. Re: JNDI and NotSerializableException
                            sharris

                            I'm still not clear why you added the third line to jndi.properties. Because of this additional line JBoss is treating your local calls as remote, so why wouldn't you expect to have to serialize your objects.

                            • 11. Re: JNDI and NotSerializableException
                              darranl

                              sharris,

                              I think that we have now realised that the addition of the third line to the jndi.properties was made in error after reading some past posts.

                              The comment at the top of the file was added when a number of forum users were advising each other to edit the file without realising the implications, I think it was these posts that were found.

                              With regards to serialization the JBoss JNDI implementation will serialize all objects bound anyway unless they implement the referenceble interface.