Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala 2.9 Bridge-Method

I'm using Scala 2.9.1

I've defined a Logging trait as such:

 trait Logging {
    def debug(msg: String, throwables: Throwable*) = ....
    ....
 }

And I have a JMSPublisher class which mixes-in the Logging trait:

 class JMSPublisher extends Publisher with Logging {
    def publishProducts(list: List[_ <: Product]) = ....
    def publish(list: Seq[Product]) = ....
 }

This all compiles fine. My issue is that I have a user who wants to load my JMSPublisher into Spring. He's using Spring 2.5.6.

When the ApplicationContext is loaded during startup, the app crashes with an IllegalStateException, complaining that it can't find a bridged-method related to my Logging trait.

Initialization of bean failed; nested exception is java.lang.IllegalStateException: Unable to locate bridged method for bridge method 'public void com.app.messaging.JmsPublisher.debug(java.lang.String, scala.collection.Seq)' 
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
    .....stack trace follows.......

This code worked under Scala-2.8, and I heard that Scala is marking trait that have some methods as bridged in 2.9. I think this is what is causing Spring to fail. I can't upgrade to Scala-2.9 if my class can't be loaded by Spring.

Has anyone run into this issue? Is there any fix or work-around?

like image 883
shj Avatar asked Nov 04 '11 19:11

shj


1 Answers

We saw the same thing. I never figured out what change in Scala 2.9.x triggered this, but I think the real problem is with Spring itself.

When you mix a trait into a class, the adds synthetic methods to in the class, marked in the byte code as bridge methods, that forward to the implementation of the method in the trait.

Java also adds bridge methods to classes, when a sub-class overrides a method in a superclass or interface, but refines the return type. Because the return type is part of the method signature at the bytecode level, a forwarding method is needed so that clients who only know about the parent method signature can still call the method in the subclass. (More details: What Method.isBridge used for?)

Spring inspects the bytecode for bridge methods for reasons described in the article A Bridge Too Far. The name of that article is ironic -- Spring calls this "a perfect example of Spring solving the hard infrastructure problems that Java developers face and integrating them into the application stack", but it makes too many assumptions about the source of the bytecode, and worse, can't be disabled.

Short term workaround, is to avoid mixing traits into classes you use in Spring. You should lodge a bug with Spring to allow you to disable this check for non-Java bytecode.

like image 174
retronym Avatar answered Oct 06 '22 10:10

retronym