Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get Groovy and JAXB to play nice together

Tags:

java

jaxb

groovy

I am trying to get JAXB to work with a groovy class of mine, however, it appears it doesn't work but the java version does. Here is the code...

Here are the Scenarios:

If 2 and 3 are uncommented it works fine.

If 1 and 4 are uncommented I get:

 com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException:
       2 counts of IllegalAnnotationExceptions
 groovy.lang.MetaClass is an interface, and JAXB can't handle interfaces.

If 1 and 5 are uncommented I get:

  javax.xml.bind.JAXBException: class org.oclc.presentations.simplejaxb.PlayerGroovy
        nor any of its super class is known to this context.

Any ideas?

Java:

    import javax.xml.bind.annotation.XmlRootElement;

    @XmlRootElement
    public class Player {
    }

Groovy:

    import javax.xml.bind.annotation.XmlRootElement

    @XmlRootElement
    public class PlayerGroovy {
    }

Test:

    import org.junit.Test
    import javax.xml.bind.JAXBContext
    import javax.xml.bind.Marshaller
    import org.junit.Assert

    class PlayerTest {
        @Test
        public void testJaXB(){
            //1 PlayerGroovy player = new PlayerGroovy()
            //2 Player player = new Player()
            StringWriter writer = new StringWriter();
            //3 JAXBContext context = JAXBContext.newInstance(Player.class);
            //4 JAXBContext context = JAXBContext.newInstance(PlayerGroovy.class);
            //5 JAXBContext context = JAXBContext.newInstance(PlayerGroovy.getClass());
            Marshaller m = context.createMarshaller();
            m.marshal(player, writer);
            println(writer)
            Assert.assertTrue(true)
        }
    }
like image 747
Jackie Avatar asked Jul 21 '09 19:07

Jackie


People also ask

Why was JAXB removed?

JAXB was integrated within the JVM itself, so you didn't need to add any code dependency to have the functionality within your application. But with the modularization performed in JDK 9, it was removed as the maintainers wanted to have a smaller JDK distribution that only contains the core concepts.

Can we write Java code in Groovy?

Groovy scripts can use any Java classes. They can be compiled to Java bytecode (in . class files) that can be invoked from normal Java classes. The Groovy compiler, groovyc, compiles both Groovy scripts and Java source files, however some Java syntax (such as nested classes) is not supported yet.

Is JAXB available in Java 11?

With Java releases lower than Java 11, JAXB was part of the JVM and you could use it directly without defining additional libaries. As of Java 11, JAXB is not part of the JRE anymore and you need to configure the relevant libraries via your dependency management system, for example Maven or Gradle.


3 Answers

Uncommenting 1 and 4 is the correct way to set JAXB up with Groovy. The reason it is not working is that each Groovy Class has a metaClass property on it. JAXB is trying to expose this as a JAXB property which obviously fails. Since you don't declare the metaClass property yourself, it is not possible to annotate it to have JAXB ignore it. Instead you and set the XmlAccessType to NONE. This disable's JAXB's auto-discovery of properties to expose as XML elements. After you do that, you need to explicitly declare any fields you want exposed.

Example:

@XmlAccessorType( XmlAccessType.NONE ) @XmlRootElement public class PlayerGroovy {     @XmlAttribute     String value } 
like image 185
Chris Dail Avatar answered Oct 28 '22 03:10

Chris Dail


I was having the same problem while exposing a Grails GORM object. After researching the solution posted above, using @XmlAccessorType( XmlAccessType.NONE ), I quickly grew tired of marking everything as @XmlAttribute.

I'm having plenty of success using:

@XmlAccessorType( XmlAccessType.FIELD )
@XmlRootElement
public class PlayerGroovy {
    String value
}

See: XmlAccessType

Thanks to the original answer for getting me started in the right direction.

like image 26
Steve Ardis Avatar answered Oct 28 '22 03:10

Steve Ardis


The solution does not seem to work on an abstract subclass. I think it's because the compiler does not generate the getMetaClass override code. I ended up mimicking the steps from this question as follows:

@XmlAccessorType(XmlAccessType.NONE)
package groovy.lang;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

Yes, it's kinda weird. In my case, I have code like this:

package pkg;
abstract class ScriptMomma extends groovy.lang.Script {
    // write some nice supporting code here
}

And to execute my scripts, I have:

def config = new org.codehaus.groovy.control.CompilerConfiguration()
config.scriptBaseClass = 'pkg.ScriptMomma'
ScriptMomma mine = new GroovyShell(config).evaluate(scriptFile, 'TheOne')

I'd prefer a better solution, but right now this is all I have.

like image 37
ngreen Avatar answered Oct 28 '22 03:10

ngreen