Search code examples
javajpanetbeansopenjpaapache-tomee

Entities that uses stream filters yields StringIndexOutOfBoundsException on OpenJPA with TomEE


I am using OpenJPA 2.0 with TomEE 1.7.2 on NetBeans 8.0.2, it was working fine before I added some Java 8 codes in an Entity class, but now I'm getting a StringIndexOutOfBoundsException while starting TomEE.

I have a class Phone

@Entity
@Table(name = "PHONES")
public class Phone implements Serializable, Cloneable {
    @Id
    @Column(name = "PHONE_ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "PHONE_NUMBER", nullable = false)
    private String number;

    @ManyToOne
    @JoinColumn(name = "PERSON_ID", nullable = false)
    private Person owner;
}

I have a class Person.

@Entity
@Table(name = "PEOPLE")
public class Person implements Serializable, Cloneable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "PERSON_ID")
    private long id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner", fetch = FetchType.EAGER)
    private Set<Phone> phones;
}

I have a method setPhones that used a for to set the owner correctly:

public void setPhones(Set<Phone> phones) {
    if (phones != null && !phones.isEmpty()) {
        for (Phone phone : phones) {
            if (phone != null) {
                phone.setOwner(this);
            }
        }
    }
    this.phones = phones;
}

Then, I changed to use the java 8 streams/filters

public void setPhones(Set<Phone> phones) {
    if (phones != null && !phones.isEmpty()) {
        phones.stream().filter((phone) -> (phone != null)).forEach((phone) -> {
            phone.setOwner(this);
        });
    }
    this.phones = phones;
}

And after this change I'm getting this message on startup:

WARNING: An exception was thrown while attempting to perform class file transformation on "com.mydomain.Person": java.lang.StringIndexOutOfBoundsException: String index out of range: 29789
at java.lang.String.checkBounds(String.java:373)
at java.lang.String.<init>(String.java:413)
at serp.bytecode.lowlevel.ConstantPoolTable.readString(ConstantPoolTable.java:112)
at serp.bytecode.lowlevel.ConstantPoolTable.readString(ConstantPoolTable.java:174)
at org.apache.openjpa.enhance.PCClassFileTransformer.isEnhanced(PCClassFileTransformer.java:241)
at org.apache.openjpa.enhance.PCClassFileTransformer.needsEnhance(PCClassFileTransformer.java:195)
at org.apache.openjpa.enhance.PCClassFileTransformer.transform0(PCClassFileTransformer.java:140)
at org.apache.openjpa.enhance.PCClassFileTransformer.transform(PCClassFileTransformer.java:127)
at org.apache.openjpa.persistence.PersistenceProviderImpl$ClassTransformerImpl.transform(PersistenceProviderImpl.java:292)
at org.apache.openejb.persistence.PersistenceUnitInfoImpl$PersistenceClassFileTransformer.transform(PersistenceUnitInfoImpl.java:362)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2957)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1210)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1690)
at org.apache.tomee.catalina.LazyStopWebappClassLoader.loadClass(LazyStopWebappClassLoader.java:171)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)
at org.apache.openejb.cdi.CdiScanner.load(CdiScanner.java:299)
at org.apache.openejb.cdi.CdiScanner.process(CdiScanner.java:248)
at org.apache.openejb.cdi.CdiScanner.init(CdiScanner.java:182)
at org.apache.openejb.cdi.OpenEJBLifecycle.startApplication(OpenEJBLifecycle.java:180)
at org.apache.openejb.cdi.ThreadSingletonServiceImpl.initialize(ThreadSingletonServiceImpl.java:160)
at org.apache.openejb.cdi.CdiBuilder.build(CdiBuilder.java:41)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:846)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:652)
at org.apache.tomee.catalina.TomcatWebAppBuilder.startInternal(TomcatWebAppBuilder.java:1261)
at org.apache.tomee.catalina.TomcatWebAppBuilder.configureStart(TomcatWebAppBuilder.java:1100)
at org.apache.tomee.catalina.GlobalListenerSupport.lifecycleEvent(GlobalListenerSupport.java:130)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5416)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:677)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1912)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:744)

My "solution" was to put the previous method back, it is working fine. But I would like to be able to use Java 8 in my project. Am I doing something wrong? If so, what?


Solution

  • It looks like TomEE 1.7.2 uses an older version (1.14.1) of the "serp" library for doing bytecode manipulation of entity beans. Unfortunately that version doesn't support classes that use some of the new Java 8 features (especially lambdas). You might try updating to the latest version of serp (though there may be incompatibilities) to see if you can get things working that way.

    Check this serp issue and this OpenJPA issue which both appear to be fixed (meaning that eventually TomEE should get updated to have full Java 8 support in its JPA entity beans). And they may shed some light on whether/how you can manually update the libraries in TomEE 1.7.2 to get support sooner.