Results 1 to 10 of 17

Thread: Spring Roo and Google App Engine

Hybrid View

  1. #1
    Join Date
    May 2005
    Location
    BEEK, The Netherlands
    Posts
    230

    Default Spring Roo and Google App Engine

    Will it be easy to develop a Roo application and deploy it on Google App Engine?

  2. #2
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    There is no theoretical prohibition to doing this based on Roo's architecture, but you need to consider that GAE's data store does not have the traditional ACID transactions many applications need.

    GAE Java support also prefers uses work through JDO instead of JPA, with Roo alpha 2 offering JPA support only. You might notice we've written our commands in a form that is intended to specifically request JPA usage where persistence is involved. This was undertaken so we can easily add JDO support in the future. There is no specific timeframe for this, but it's not really complicated to do. The metadata model within Roo has already been designed to support persistence technology independence, so my best advice is "stay tuned".

    Don't forget in the meantime you can very easily deploy Roo applications to EC2. This is where our "voting application" was running from that we developed at last week's SpringOne keynote. Indeed if you download our now-free STS 2.1.0 (the next series) IDE, you'll see it has inbuilt EC2 support. This means you can build a Roo app entirely within STS 2.1.0+, then deploy it straight to an Amazon Web Services cloud environment. This is pretty neat, especially as with the EC2 approach you receive full ACID transactions and can continue to use ORMs like Hibernate, which are likely to be more familiar to most developers than JDO mappers. It also means you can take the same WAR and deploy it to a non-cloud environment, giving you total portability away from the AWS cloud environment should you wish to use it.
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  3. #3
    Join Date
    May 2005
    Location
    BEEK, The Netherlands
    Posts
    230

    Default

    GAE/J also support JPA out of the box. See http://code.google.com/appengine/doc.../usingjpa.html

  4. #4
    Join Date
    Nov 2006
    Location
    Columbus, OH
    Posts
    143

    Default

    So I ran across this thread and thought I'd voice my findings so far...

    My setup:

    Spring Framework 3.0.0-M4
    Spring Roo 1.0.0-RC1
    Google AppEngine API v1.2.5

    I can follow the Roo instructions 100%. My roo script appears as:

    Code:
    create project -topLevelPackage family.abe -projectName family-abe
    install jpa -provider HIBERNATE -database MYSQL
    new persistent class jpa -name ~.reference.EventType -testAutomatically
    new persistent class jpa -name ~.domain.Event -testAutomatically
    add field string -class ~.reference.EventType -fieldName name -notNull -sizeMax 30
    add field string -class ~.reference.EventType -fieldName description -sizeMax 255
    add field string -class ~.domain.Event -fieldName name -notNull -sizeMin 5 -sizeMax 60
    add field date jdk -type java.util.Date -class ~.domain.Event -fieldName eventDate -notNull
    add field date jdk -type java.util.Date -class ~.domain.Event -fieldName rsvp -notNull
    add field string -class ~.domain.Event -fieldName description -sizeMax 255
    add field string -class ~.domain.Event -fieldName location -sizeMax 255
    add field string -class ~.domain.Event -fieldName directions -sizeMax 255
    add field string -class ~.domain.Event -fieldName notes -sizeMax 255
    add field boolean -class ~.domain.Event -fieldName alcohol
    add field boolean -class ~.domain.Event -fieldName food
    add field boolean -class ~.domain.Event -fieldName showLocation
    add field boolean -class ~.domain.Event -fieldName showDirections
    add field reference jpa -class ~.domain.Event -fieldName type -type ~.reference.EventType -notNull
    new controller automatic -name ~.web.EventTypeController -formBackingObject ~.reference.EventType
    new controller automatic -name ~.web.EventController -formBackingObject ~.domain.Event
    configure logging -level INFO -package ALL_SPRING
    configure logging -level WARN -package AOP
    configure logging -level INFO -package PERSISTENCE
    configure logging -level DEBUG -package PROJECT
    configure logging -level WARN -package SECURITY
    configure logging -level WARN -package TRANSACTIONS
    configure logging -level INFO -package WEB
    I create src/main/webapp/appengine-web.xml with the usual contents and then I modify my pom.xml as so:

    Code:
    <project>
        ...
        <repositories>
            ...
            <repository>
                <id>DataNucleus_Repos</id>
                <name>DataNucleus Repository</name>
                <url>http://www.datanucleus.org/downloads/maven</url>
                <layout>legacy</layout>
            </repository>
            <repository>
                <id>DataNucleus_Repos2</id>
                <name>DataNucleus Repository</name>
                <url>http://www.datanucleus.org/downloads/maven2</url>
            </repository>
        </repositories>
        <pluginRepositories>
            ...
            <pluginRepository>
                <id>DataNucleus_2</id>
                <url>http://www.datanucleus.org/downloads/maven2/</url>
            </pluginRepository>
        </pluginRepositories>
        <dependencies>
            ...
            <!-- Google App Engine Dependencies which are manually installed -->
            <dependency>
                <groupId>com.google.appengine</groupId>
                <artifactId>appengine-api-1.0-sdk</artifactId>
                <version>1.2.5</version>
            </dependency>
            <dependency>
                <groupId>com.google.appengine</groupId>
                <artifactId>appengine-tools-api</artifactId>
                <version>1.2.5</version>
            </dependency>
    
            <!-- Data Nucleus Dependencies -->
            <dependency>
                <groupId>org.datanucleus</groupId>
                <artifactId>datanucleus-appengine</artifactId>
                <version>1.0.2.final</version>
            </dependency>
            <dependency>
                <groupId>org.datanucleus</groupId>
                <artifactId>datanucleus-core</artifactId>
                <version>1.1.4</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.datanucleus</groupId>
                <artifactId>datanucleus-jpa</artifactId>
                <version>1.1.4</version>
            </dependency>
            <dependency>
                <groupId>org.datanucleus</groupId>
                <artifactId>datanucleus-enhancer</artifactId>
                <version>1.1.1</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.geronimo.specs</groupId>
                <artifactId>geronimo-jpa_3.0_spec</artifactId>
                <version>1.1.1</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.geronimo.specs</groupId>
                <artifactId>geronimo-jta_1.1_spec</artifactId>
                <version>1.1.1</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>javax.jdo</groupId>
                <artifactId>jdo2-api</artifactId>
                <version>2.3</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>asm</groupId>
                <artifactId>asm</artifactId>
                <version>3.2</version>
                <scope>compile</scope>
            </dependency>
    
            <!-- Use ASM 1.5.3 for Spring at runtime, but we need 3.0+ for Data Nucleus during compile -->
            <dependency>
                <artifactId>com.springsource.org.objectweb.asm</artifactId>
                <groupId>org.objectweb.asm</groupId>
                <version>1.5.3</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <artifactId>com.springsource.org.objectweb.asm.attrs</artifactId>
                <groupId>org.objectweb.asm</groupId>
                <version>1.5.3</version>
                <scope>runtime</scope>
            </dependency>
    
            <!-- Included to get rid of a silly error when building this with maven -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>1.6.3</version>
            </dependency>
        </dependencies>
        <plugins>
                <plugin>
                    <groupId>org.datanucleus</groupId>
                    <artifactId>maven-datanucleus-plugin</artifactId>
                    <version>1.1.0</version>
                    <configuration>
                        <api>JPA</api>
                        <enhancerName>ASM</enhancerName>
                        <log4jConfiguration>src/main/resources/META-INF/spring/log4j.properties</log4jConfiguration>
                        <persistenceUnitName>transactions-optional</persistenceUnitName>
                        <verbose>true</verbose>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>process-classes</phase>
                            <goals>
                                <goal>enhance</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
        </plugins>
    </project>
    Then I replace src/main/resources/META-INF/persistence.xml with the contents:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    
      <persistence-unit name="transactions-optional">
        <provider>org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider</provider>
        <class>family.abe.domain.Event</class>
        <class>family.abe.reference.EventType</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
          <property name="datanucleus.NontransactionalRead" value="true"/>
          <property name="datanucleus.NontransactionalWrite" value="true"/>
          <property name="datanucleus.ConnectionURL" value="appengine"/>
        </properties>
      </persistence-unit>
    </persistence>
    Additionally, I create src/main/resources/META-INF/orm.xml with the contents:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
        version="1.0">
    
        <entity class="family.abe.reference.EventType">
            <id-class class="java.lang.Long" />
        </entity>
        <entity class="family.abe.domain.Event">
            <id-class class="java.lang.Long" />
        </entity>
    
    </entity-mappings>
    I also modify src/main/resources/META-INF/spring/log4j.properties adding the following:

    Code:
    # Define the destination and format of logging for Data Nucleus
    log4j.appender.A1=org.apache.log4j.FileAppender
    log4j.appender.A1.File=datanucleus.log
    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
    log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
    
    # DataNucleus Categories
    log4j.category.DataNucleus.JDO=DEBUG, A1
    log4j.category.DataNucleus.JPA=DEBUG, A1
    log4j.category.DataNucleus.Cache=DEBUG, A1
    log4j.category.DataNucleus.MetaData=DEBUG, A1
    log4j.category.DataNucleus.General=DEBUG, A1
    log4j.category.DataNucleus.Utility=DEBUG, A1
    log4j.category.DataNucleus.Transaction=DEBUG, A1
    log4j.category.DataNucleus.Datastore=DEBUG, A1
    log4j.category.DataNucleus.ClassLoading=DEBUG, A1
    log4j.category.DataNucleus.Plugin=DEBUG, A1
    log4j.category.DataNucleus.ValueGeneration=DEBUG, A1
    
    log4j.category.DataNucleus.Enhancer=DEBUG, A1
    log4j.category.DataNucleus.SchemaTool=DEBUG, A1
    Regards,

    Joshua Preston

    --

    "The Guide says that there is an art to flying," said Ford, "or rather a knack. The knack lies in learning how to throw yourself at the ground and miss."

  5. #5
    Join Date
    Nov 2006
    Location
    Columbus, OH
    Posts
    143

    Default

    I then run mvn -e -o clean package with the following output (trimmed for size)

    Code:
    + Error stacktraces are turned on.
    
    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Building family-abe
    [INFO]    task-segment: [clean, compile, package]
    [INFO] ------------------------------------------------------------------------
    [INFO] [clean:clean]
    [INFO] Deleting directory /Users/jpreston/src/family-abe/target
    [INFO] [aspectj:compile {execution: default}]
    [INFO] [resources:resources]
    [INFO] Using encoding: 'UTF-8' to copy filtered resources.
    [INFO] [compiler:compile]
    [INFO] Nothing to compile - all classes are up to date
    [INFO] [aspectj:compile {execution: default}]
    [INFO] [resources:resources]
    [INFO] Using encoding: 'UTF-8' to copy filtered resources.
    [INFO] [compiler:compile]
    [INFO] Nothing to compile - all classes are up to date
    [INFO] [datanucleus:enhance {execution: default}]
    [INFO] DataNucleus Enhancer : Using ClassEnhancer "ASM" for API "JPA"
    
    MetaDataManager : Input=(XML, Annotations), XML-Validation=true
    Parsing MetaData file "file:/Users/jpreston/src/family-abe/target/classes/META-INF/persistence.xml" using handler "persistence" (validation="true")
    XML Entity Public="" System="http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" : using local source "/org/datanucleus/jpa/jpa_persistence_1_0.xsd"
    MetaData Management : Loading Metadata for persistence-unit "transactions-optional" ...
    Parsing MetaData file "file:/Users/jpreston/src/family-abe/target/classes/META-INF/orm.xml" using handler "jpa" (validation="true")
    XML Entity Public="" System="http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" : using local source "/org/datanucleus/jpa/jpa_orm_1_0.xsd"
    
    Populating all MetaData ...
    Populating Meta-Data for class family.abe.reference.EventType.
    Class "family.abe.reference.EventType" has been specified with JPA annotations so using those.
    Ignoring metadata for field family.abe.reference.EventType.description since we already have MetaData for the property family.abe.reference.EventType.description
    Ignoring metadata for field family.abe.reference.EventType.name since we already have MetaData for the property family.abe.reference.EventType.name
    Class "family.abe.reference.EventType" is having internal MetaData definition updated with Annotations information
    Populating Meta-Data for class family.abe.domain.Event.
    Class "family.abe.domain.Event" has been specified with JPA annotations so using those.
    Ignoring metadata for field family.abe.domain.Event.eventDate since we already have MetaData for the property family.abe.domain.Event.eventDate
    Ignoring metadata for field family.abe.domain.Event.location since we already have MetaData for the property family.abe.domain.Event.location
    Ignoring metadata for field family.abe.domain.Event.type since we already have MetaData for the property family.abe.domain.Event.type
    Ignoring metadata for field family.abe.domain.Event.directions since we already have MetaData for the property family.abe.domain.Event.directions
    Ignoring metadata for field family.abe.domain.Event.description since we already have MetaData for the property family.abe.domain.Event.description
    Ignoring metadata for field family.abe.domain.Event.name since we already have MetaData for the property family.abe.domain.Event.name
    Ignoring metadata for field family.abe.domain.Event.notes since we already have MetaData for the property family.abe.domain.Event.notes
    Class "family.abe.domain.Event" is having internal MetaData definition updated with Annotations information
    Annotations information
    Initialising all MetaData ...
    Initialising Meta-Data for class family.abe.reference.EventType.
    
    [ERROR] --------------------
    [ERROR]  Standard error from the DataNucleus tool + org.datanucleus.enhancer.DataNucleusEnhancer :
    [ERROR] --------------------
    [ERROR] Exception in thread "main" java.lang.AbstractMethodError: org.datanucleus.jpa.JPAAdapter.isValidPrimaryKeyClass(Ljava/lang/Class;Lorg/datanucleus/metadata/AbstractClassMetaData;Lorg/datanucleus/ClassLoaderResolver;ILorg/datanucleus/metadata/MetaDataManager;)Z
    	at org.datanucleus.metadata.AbstractClassMetaData.validateObjectIdClass(AbstractClassMetaData.java:1082)
    	at org.datanucleus.metadata.ClassMetaData.initialise(ClassMetaData.java:599)
    	at org.datanucleus.metadata.MetaDataManager$2.run(MetaDataManager.java:2442)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.datanucleus.metadata.MetaDataManager.initialiseAbstractClassMetaData(MetaDataManager.java:2436)
    	at org.datanucleus.metadata.MetaDataManager.initialiseClassMetaData(MetaDataManager.java:2295)
    	at org.datanucleus.metadata.MetaDataManager.initialiseFileMetaData(MetaDataManager.java:2243)
    	at org.datanucleus.metadata.MetaDataManager.initialiseFileMetaDataForUse(MetaDataManager.java:938)
    	at org.datanucleus.metadata.MetaDataManager.loadPersistenceUnit(MetaDataManager.java:851)
    	at org.datanucleus.enhancer.DataNucleusEnhancer.getFileMetadataForInput(DataNucleusEnhancer.java:808)
    	at org.datanucleus.enhancer.DataNucleusEnhancer.enhance(DataNucleusEnhancer.java:551)
    	at org.datanucleus.enhancer.DataNucleusEnhancer.main(DataNucleusEnhancer.java:1260)
    
    [ERROR] --------------------
    [INFO] ------------------------------------------------------------------------
    [ERROR] BUILD ERROR
    [INFO] ------------------------------------------------------------------------
    [INFO] The DataNucleus tool org.datanucleus.enhancer.DataNucleusEnhancer exited with a non-null exit code.
    [INFO] ------------------------------------------------------------------------
    [INFO] Trace
    org.apache.maven.lifecycle.LifecycleExecutionException: The DataNucleus tool org.datanucleus.enhancer.DataNucleusEnhancer exited with a non-null exit code.
    	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:583)
    	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:499)
    	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:478)
    	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:330)
    	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:291)
    	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:142)
    	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:336)
    	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:129)
    	at org.apache.maven.cli.MavenCli.main(MavenCli.java:287)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:597)
    	at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
    	at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
    	at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
    	at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
    Caused by: org.apache.maven.plugin.MojoExecutionException: The DataNucleus tool org.datanucleus.enhancer.DataNucleusEnhancer exited with a non-null exit code.
    	at org.datanucleus.maven.AbstractDataNucleusMojo.executeCommandLine(AbstractDataNucleusMojo.java:263)
    	at org.datanucleus.maven.AbstractEnhancerMojo.enhance(AbstractEnhancerMojo.java:184)
    	at org.datanucleus.maven.AbstractEnhancerMojo.executeDataNucleusTool(AbstractEnhancerMojo.java:81)
    	at org.datanucleus.maven.AbstractDataNucleusMojo.execute(AbstractDataNucleusMojo.java:107)
    	at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:451)
    	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:558)
    	... 16 more
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 14 seconds
    [INFO] Finished at: Thu Sep 17 21:25:07 EDT 2009
    [INFO] Final Memory: 27M/81M
    [INFO] ------------------------------------------------------------------------
    I'm fresh out of ideas from here; I've tried manually compiling AspectJ and then manually running the Data Nucleus Enhancer, however, the result is the same. It's getting late now, but hopefully I'll get some time to dig into the source for everything and see where the hiccup is.

    Anyone have any ideas where to look or go to next until then?

    Thanks in advance!

    ** Update

    This was caused by the use of the incorrect version of the datanucleus enhancer plugin. I switched the plugin version to 1.1.4 and it worked properly.
    Last edited by jpreston; Sep 21st, 2009 at 07:08 AM.
    Regards,

    Joshua Preston

    --

    "The Guide says that there is an art to flying," said Ford, "or rather a knack. The knack lies in learning how to throw yourself at the ground and miss."

  6. #6
    Join Date
    Nov 2006
    Location
    Columbus, OH
    Posts
    143

    Default

    I've managed to get the Data Nucleus Enhancer to work with the Roo Project, and the Roo application deployed to the dev_appsrv for Google AppEngine. However, there appears to be issues with transaction management and the bytecode enhancement. When it runs, it runs VERY slowly and some of my domain classes are being looked up at java.lang, which is strange. I'm going to continue looking at it, and see what the deal is.

    ** Update
    JSPs compile painfully slow on the dev app server, but once deployed on app engine it is not an issue because all JSPs are precompiled.
    Last edited by jpreston; Sep 21st, 2009 at 07:19 AM.
    Regards,

    Joshua Preston

    --

    "The Guide says that there is an art to flying," said Ford, "or rather a knack. The knack lies in learning how to throw yourself at the ground and miss."

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •