3

I am working with protobufs with the play framework 2.1.3 without issues. I then needed to convert the protobufs to JSON, so I included

"com.googlecode.protobuf-java-format" % "protobuf-java-format" % "1.2"

in Build.scala.

Trying to covert any protobuf to JSON using

JsonFormat.printToString(message);

This leads to the following error when running in dev mode (started with play run)

play.api.Application$$anon$1: Execution exception[[RuntimeException: java.lang.NoClassDefFoundError: com/google/protobuf/InvalidProtocolBufferException]]
...
Caused by: java.lang.NoClassDefFoundError: com/google/protobuf/InvalidProtocolBufferException
...
Caused by: java.lang.ClassNotFoundException: com.google.protobuf.InvalidProtocolBufferException
at java.net.URLClassLoader$1.run(URLClassLoader.java:202) ~[na:1.6.0_51]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.6.0_51]
at java.net.URLClassLoader.findClass(URLClassLoader.java:190) ~[na:1.6.0_51]
at java.lang.ClassLoader.loadClass(ClassLoader.java:306) ~[na:1.6.0_51]
at java.lang.ClassLoader.loadClass(ClassLoader.java:247) ~[na:1.6.0_51]
at sbt.PlayCommands$$anonfun$53$$anonfun$55$$anon$2.loadClass(PlayCommands.scala:535) ~[na:na]

If play is started in production mode I do not have any errors.

I have been able to get it to work in dev mode if I put the source code for protobuf-java-format in my app folder. As a temporary solution this works, but I would like to know the correct way to deal with this problem.

Additional information: Per suggestion below, I have checked play classpath, play dependencies, and searched my system and I only have one copy of the jar being included.

I can run without problems:

Exception e = new InvalidProtocolBufferException()

NoClassDefFoundError is thrown when I try to use any static method from protobuf-java-format library. For example:

XmlFormat.printToString(message)

Does not work in dev mode but does work in production (play start). Interestingly the class it says it can't find is different:

[RuntimeException: java.lang.NoClassDefFoundError: com/google/protobuf/Message]

I am using the methods from the protobuf library without problems elsewhere, so I know they are being included in the class path.

From google, I have been able to find one other instance that has similar problems: https://groups.google.com/forum/#!msg/play-framework/i0RNcu8PZOY/J7cy18xsg3oJ

I have not been able to figure out how to refactor the code to make it work.

Eric K
  • 33
  • 1
  • 4

1 Answers1

0

Are you sure that class exists in 1.2? I see it exists in version 2.3.

http://grepcode.com/file/repo1.maven.org/maven2/com.google.protobuf/protobuf-java/2.3.0/com/google/protobuf/InvalidProtocolBufferException.java

It is sounding like a classloader issue then where the protobuf-java-format jar is in one classloader that has no access to the other jar. The best bet is to make sure this jar and the other protobuf jar end up in the same directory when you are running the app so they end up in the same classloader.

Other things you can do is call class in each and get the classloader and fool around with getting the classloaders parents as well to see what the classloader heirarchy looks like.

Another very useful method to play around with when debugging is XXXXX.class.getProtectionDomain().getCodeSource().getLocation()

replace XXXXX with a class that exists in protobuf like that Exception class that your class is having no problem loading and protobuf-java-format is having a problem loading and also any class from protobuf-java-format. This will tell you where the JVM is loading the two jars from.

Dean Hiller
  • 19,235
  • 25
  • 129
  • 212
  • I am using the 2.3 for the protobuf library. [Protobuf java format](https://code.google.com/p/protobuf-java-format/) is a separate project for serializing the protobuf to JSON, XML, or HTML. – Eric K Sep 18 '13 at 18:44
  • simplify the problem then...take out protobuf-java-format and instead add code like Exception e = new InvalidProtocolBufferException() to see if that works first. How are you including the jar and are you sure there is not multiple versions on the classpath? Make sure you search the filesystem for all *.jars and verify you don't have two versions. – Dean Hiller Sep 18 '13 at 18:51
  • Tried to included details following up on all suggestions. I edited the post above with the details – Eric K Sep 18 '13 at 22:47
  • Seems like it is a class loader problem. The problem occurs when the two libraries are included differently. For example, if I include 1 project in the lib folder or put its source in the app folder and include the other project by using Build.scala, then I am able to consistently produce errors in dev mode. If I include both projects in the same way, no errors are produced in dev mode. – Eric K Sep 19 '13 at 16:52
  • yup, sounds about right. happens all the time. The above code is how to debug situations like that especially the ProtectionDomain stuff. If they are in different directories in java, chances are they are loaded differently into different classloaders. Usually one of those directories is above the other one and is the parent classloader that everyone has access to and the other one is to wall off different applications that may use different versions of 3rd party libraries. – Dean Hiller Sep 19 '13 at 16:55