7 Replies Latest reply on Oct 16, 2004 9:24 AM by frito

    InvalidClassException when passing obj to session bean.

    rgc3679

      I use JBoss 3.2.2 and JVM 1.4.2.

      My app is deployed as an EAR and uses RMI over HTTP to communicate between client and server.

      When trying to pass one of my objects from the client to the server so that it can be stored in the DB I am getting an InvalidClassException.

      The code snippet where this happens follows:
      -------------
      public long checkinSite(SiteData sData, boolean requestLock) {
      logger.info("checkinSite_entry");

      // Setup
      long result = 0L;

      try {
      long siteId = sData.getId();
      logger.info("checkinSite - siteId = " +siteId);

      // Get site bean
      Object siteObj = ic.lookup("tacplanner/site");
      SiteHome siteHome = (SiteHome) PortableRemoteObject.narrow(siteObj, SiteHome.class);
      Site site = (Site) PortableRemoteObject.narrow(siteHome.create(), Site.class);

      // Checkin according to whether site is new or existing
      if(siteId < 0) {
      // Checkin new site - get site id
      long newSiteId = site.getNextSiteId();

      if(newSiteId != 0) {
      logger.info("checkinSite - newSiteId = " +newSiteId);
      sData.setId(newSiteId);
      result = newSiteId;

      // Perform rename of all site, bldg and flr files
      try {
      sData.renameAll(siteId, newSiteId);
      }
      catch(Exception ex) {
      throw new CheckinException("site id mismatch during " +ex.toString() +" replace");
      }

      // Save modified site data
      Constants.SITEDATA.setSiteData(sData);

      // Add site to database
      SiteData sDataCopy = new SiteData(sData);
      long beanMsg = site.addNewSite(sDataCopy);
      if(beanMsg <= 0) throw new CheckinException("error while adding site to database, code = " +beanMsg);
      else logger.info("checkinSite - SUCCESS adding site to database having siteId = " +newSiteId);

      -------------

      The exception happens on line - site.addNewSite(sDataCopy);

      Making a copy of my object and passing solved this same problem, when my object was less populated - but now that I've added more data to the object the exception has returned.

      You can see the SiteData.java, SiteBean.java and the server log at:
      http://www.carpenterdev.com:890/bobc/ejb

      I appreciate any help in solving this annoying problem!

      --BobC

        • 1. Re: InvalidClassException when passing obj to session bean.
          frito

          I don't think it has to do with less or more population. But at least on object does match these criteria:


          The serial version of the class does not match that of the class descriptor read from the stream
          The class contains unknown datatypes
          The class does not have an accessible no-arg constructor


          • 2. Re: InvalidClassException when passing obj to session bean.
            rgc3679

            Frito,

            Let's examine each of the possibilities for an InvalidClassException:

            1) The serial version of the class does not match that of the class descriptor read from the stream

            This is a possibility because the client JARs are loaded to the client machine using Java WebStart. But, like I said previously, this has been working until I enriched the object with more data. The new data, though, in fact all the data, is serializable.

            2) The class contains unknown datatypes

            This is not a possibility - all data types used are Java native types like String, Integer...

            3) The class does not have an accessible no-arg constructor

            No, it does,

            So, that leaves option 1. Does anyone out there have similar experience using WebStart to transfer client JARs that involve classes that get sent over RMI to EJBs?

            Thanks,

            --BobC

            • 3. Re: InvalidClassException when passing obj to session bean.
              frito

              Since I can't follow the link above, I suppose SiteData only contains standard types / Objects (as mentioned above) and you are really sure, the version deployed with JBoss is the same version provided by your Web Start server and clients and servers are running on compatible JREs ;-)

              Does SiteData provide a fix serialVersionUID? Is the standard serialisation mechanism enough for SiteData or do you have to override readObject and writeObject?

              If all this doesn't help you should focus on the Web Start configuration.

              Other ideas out there?

              • 4. Re: InvalidClassException when passing obj to session bean.
                rgc3679

                Frito,

                Why can't you follow my link? I wish you could because I'd appreciate another set of eyes looking at my classes. No, SiteData does not provide a fixed serialVersionUID - should it? I'm not familiar with the requirements for having a fixed one.

                I hadn't thought about overriding readObject and writeObject. Not really sure what to do here, or if it will solve anything.

                I am positive that in my test cases my client and server both use JVM 1.4.2 - the server is linux; client WinXP. I'm a bit concerned about this requirement though because I don't want my clients to have to keep in-synch with the server JVM version. Is there no way around this requirement?

                Thanks,

                --BobC

                • 5. Re: InvalidClassException when passing obj to session bean.
                  rgc3679

                  Update

                  I tried adding following to SiteData:
                  private static final long serialVersionUID = 1L;

                  But still get the InvalidClassException.

                  I notice from the error in the log (see following)

                  2004-10-14 13:25:18,020 [PoolThread-9] ERROR [STDERR] java.io.InvalidClassException: javax.swing.JComponent; local class incompatible: stream classdesc serialVersionUID = 5896976265092562486, local class serialVersionUID = -5353880800724033550

                  that the complaint is from a JComponent class, not my SiteData class. I store a JLabel in a Vector in SiteData.

                  So, I guess the question is: Is there a difference between JLabel on a Linux JVM 1.4.2 and a WinXP JVM 1.4.2? If so, how to fix?

                  I understand now about serialVersionUID - if you set it directly in your class then that value will be used for comparison during serialization.

                  • 6. Re: InvalidClassException when passing obj to session bean.
                    rgc3679

                    Update

                    The problem is solved. It was due to the server using a version of JRE 1.3.1 to check the serial version number of JComponent where the client was using a JRE 1.4.2 to check.

                    Even though JBoss was running under JVM 1.4.2, and so was the client, it's the JRE that is used for checking the serial version. Once I removed the 1.3.1 JRE from the path the class comparisons worked.

                    To track it down I found all rt.jar files on my server, and then ran the java app "serialver" using each one in turn as the classpath until I found the one that returned the serialVersionUID = -5353880800724033550 for javax.swing.JComponent. It turned out to be an old JRE that was loading first in the PATH.

                    Here's the command used to check the serial version numbers:

                    $serialver -classpath rt.jar javax.swing.JComponent

                    --BobC

                    • 7. Re: InvalidClassException when passing obj to session bean.
                      frito

                      Set SerialVersionUID is calculated over the signature of your class. Provide you own ID when you want to change the signature and keep it compatible to older versions.
                      You don't have to use the save JRE on client and server. But they should be compatible.