I'm trying to implement JPA with groovy/gaelyk for Google App Engine. My environment:
IDE: Eclipse Kepler SR2
groovy-all-2.0.7.jar
gaelyk-2.0.jar
Google App Engine SDK-1.9.0
MySQL
persistence.xml
<persistence-unit name="Post1Demo">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- We are using JPA provided by Eclipselink -->
<!-- Post.groovy class is in the project's package -->
<class>com.sample.gaelyk2.Post</class>
<exclude-unlisted-classes/>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/test" />
<property name="javax.persistence.jdbc.user" value="myname" />
<property name="javax.persistence.jdbc.password" value="mypassword" />
</properties>
</persistence-unit>
src/Post.groovy under com.sample.gaelyk2
package com.sample.gaelyk2
import java.io.Serializable;
import javax.persistence.*
@Entity
@Table(name="post")
class Post implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long COLID
String body
String timestamp
String title
}
WEB-INF/groovy/welcome_db.groovy
import javax.persistence.EntityManager
import javax.persistence.Query
import javax.persistence.EntityManagerFactory
import javax.persistence.Persistence
import com.sample.gaelyk2.Post
try {
String PERSISTENCE_UNIT_NAME = "Post1Demo" // see persistence.xml
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME)
EntityManager em = factory.createEntityManager()
THE PROBLEM IS RIGHT HEREEEEEE.......
Query q = em.createQuery("from Post") // MUST match class name, case sensitive
def postList = q.getResultList()
//
// Fill up the request and forward it to index_db.gtpl
//
request.setAttribute 'posts', postList
forward 'index_db.gtpl'
} catch (Throwable t) {
println "Error in welcome_db"
forward 'index_db.gtpl'
}
I got the following exception when running localhost:8888/welcom_db.groovy from the browser. I don't have this problem when I implement the whole thing in java.
SEVERE: Unable to instrument com.sample.gaelyk2.Post. Security restrictions may not be entirely emulated.
java.lang.ArrayIndexOutOfBoundsException: 271
at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.readLabel(ClassReader.java:1880)
at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.readFrameType(ClassReader.java:1860)
at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.readFrame(ClassReader.java:1794)
at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.readCode(ClassReader.java:1214)
at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.readMethod(ClassReader.java:938)
at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.accept(ClassReader.java:669)
at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.accept(ClassReader.java:506)
at com.google.appengine.tools.development.agent.impl.Transformer.rewrite(Transformer.java:146)
at com.google.appengine.tools.development.agent.impl.Transformer.transform(Transformer.java:113)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at com.google.appengine.tools.development.IsolatedAppClassLoader.loadClass(IsolatedAppClassLoader.java:216)
at java.lang.ClassLoader.loadClass(ClassLoader.java:412)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:648)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:516)
at org.codehaus.groovy.control.ClassNodeResolver.tryAsLoaderClassOrScript(ClassNodeResolver.java:183)
at org.codehaus.groovy.control.ClassNodeResolver.findClassNode(ClassNodeResolver.java:168)
at groovy.util.GroovyScriptEngine$ScriptClassLoader$3.findClassNode(GroovyScriptEngine.java:211)
at org.codehaus.groovy.control.ClassNodeResolver.resolveName(ClassNodeResolver.java:124)
at org.codehaus.groovy.control.ResolveVisitor.resolveToOuter(ResolveVisitor.java:616)
at org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:268)
at org.codehaus.groovy.control.ResolveVisitor.visitClass(ResolveVisitor.java:1133)
at org.codehaus.groovy.control.ResolveVisitor.startResolving(ResolveVisitor.java:141)
at org.codehaus.groovy.control.CompilationUnit$9.call(CompilationUnit.java:624)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:903)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:566)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:515)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:279)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:258)
at groovy.util.GroovyScriptEngine$ScriptClassLoader.doParseClass(GroovyScriptEngine.java:247)
at groovy.util.GroovyScriptEngine$ScriptClassLoader.parseClass(GroovyScriptEngine.java:229)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:244)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:202)
at groovy.util.GroovyScriptEngine.loadScriptByName(GroovyScriptEngine.java:514)
at groovy.util.GroovyScriptEngine.createScript(GroovyScriptEngine.java:564)
at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:551)
at groovyx.gaelyk.GaelykServlet.runGroovlet(GaelykServlet.groovy:154)
at groovyx.gaelyk.GaelykServlet.doService(GaelykServlet.groovy:118)
at groovyx.gaelyk.GaelykServlet.service(GaelykServlet.groovy:87)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:127)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366)
at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349)
at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:98)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:487)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
[EL Info]: 2014-03-15 01:21:04.538--ServerSession(1464126150)--EclipseLink, version: Eclipse Persistence Services - 2.5.0.v20130507-3faac2b
[EL Info]: connection: 2014-03-15 01:21:05.859--ServerSession(1464126150)--file:/C:/Users/myuser/Documents/workspace/GaeAppGaelyk2/war/WEB-INF/classes/_Post1Demo login successful
Mar 15, 2014 1:21:06 AM com.google.appengine.tools.development.ApiProxyLocalImpl log
INFO: javax.servlet.ServletContext log: TemplateServlet: Servlet groovyx.gaelyk.GaelykTemplateServlet initialized on class groovy.text.SimpleTemplateEngine
I've been googleing for the last 2 weeks, but I could not find the solution. I suspected the problem is with Groovy Class Loader, but I don't know how to fix it.
The confusion is at the bottom of the stack trace I had the following:
file:/C:/Users/myuser/Documents/workspace/GaeAppGaelyk2/war/WEB-INF/classes/_Post1Demo login successful
Thanks.
If you need to use JPA for any reason instead of built in datastore entities support you should write your entities in Java which is 100% interoperable with Groovy. DataNucleus which is used as JPA implementation needs to instrument the classes and it's obviously unable to do it for compiled Groovy classes. You can still use Groovy and Gaelyk for the rest of your code.