On Tuesday, October 22, 2013 11:40:48 AM UTC+2, Thomas Broyer wrote:
>
>
>
> On Monday, October 21, 2013 11:11:07 PM UTC+2, Nermin wrote:
>>
>> Dear Thomas,
>>
>> thank you for your Post. I have checked my OSIV konfiguration and I have 
>> it the right way (transaction per service method).
>>
>
> Apparently not (see below)
>


OK, let me show you my OSIV code:

=========== THREAD LOCAL EM
public class ThreadLocalEntityManager {
    private static ThreadLocal<EntityManager> holder = new 
ThreadLocal<EntityManager>();
    
    private ThreadLocalEntityManager() {
    }

    public static EntityManager get() {
        return holder.get();
    }

    public static void set(EntityManager em) {
        holder.set(em);
    }
}


=========== FILTER
public class AppHandlerFilter  implements Filter {
....
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
       
        //1. Create new EntityManager for this call
        EntityManager em = factory.createEntityManager();
        ThreadLocalEntityManager.set(em);    //== Create EM

        try {
            chain.doFilter(request, response);
           
        } catch (Exception e) { //Any other Exception
            if(em.getTransaction().isActive()) {
                em.getTransaction().rollback();
            }
            logger.severe(e.getMessage());
            e.printStackTrace();
        } finally {
            if(em.isOpen()) {
                em.close();                    //== Close EM
            }
        }
    }
}


======== Entity:

@Entity
public class TestEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @org.datanucleus.api.jpa.annotations.Extension(vendorName = 
"datanucleus", key = "gae.encoded-pk", value = "true")
    private String id;
    @Version
    private Long version;

    @NotNull
    private String myName;
    @Pattern(regexp = "[^@\\s]+@[^@\\s]+\\.[A-Za-z]{2,4}", message="Invalid 
e-mail address")
    @NotNull
    private String myEmailAddress;
    
    public static TestEntity findTestEntity(String id) {
        if (id == null) {
            return null;
        }
        TestEntity te = null;
        EntityManager em = ThreadLocalEntityManager.get();
        em.getTransaction().begin();
        te = em.find(TestEntity.class, id);
        em.getTransaction().commit();
        return te;
    }

    public ProcessResponse persist() {
        EntityManager em = ThreadLocalEntityManager.get();
        em.getTransaction().begin();
        em.persist(this);
        em.refresh(this);
        em.getTransaction().commit();
        return new ProcessResponse(this.getId(), true);
    }
    
    public ProcessResponse update(){
        EntityManager em = ThreadLocalEntityManager.get();
        em.getTransaction().begin();
        em.merge(this);
        em.getTransaction().commit();
        return new ProcessResponse(true);
    }
    
...
} 


==== persistence.xml

    <persistence-unit name="emajstor_persistence" 
transaction-type="RESOURCE_LOCAL">
        <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
        
        <class>com.emajstor.server.persistence.TestEntity</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"/>
            <property 
name="datanucleus.appengine.datastoreEnableXGTransactions" value="true"/>
                        
            <property name="javax.persistence.validation.group.pre-persist" 
value="javax.validation.groups.Default, 
com.emajstor.server.persistence.validator.PrePersitValidationGroup" />
            <property name="javax.persistence.validation.group.pre-update" 
value="javax.validation.groups.Default" />
            <property name="javax.persistence.validation.group.pre-remove" 
value="" />
            
        </properties>
    </persistence-unit>

 
>
>> The debuggung in ReflectiveServiceLayer#validate showed sofar an 
>> appropriate behaviour.
>>
>
> So it correctly returns ConstraintViolations in all cases?
>

YES! Validation works fine! 
 

>  
>
>> The only problem is that the *javax.validation.ConstraintViolationException 
>> *is turned into a *java.lang.RuntimeException *in case of an entity 
>> update. (see error below.)
>>
>
> There shouldn't be any ConstraintViolation*Exception*.
>

Why shouldn't be there a ConstraintViolation*Exception*?? The entity 
contains constraint violation because the provided emailAddress is 
purposely made wrong!

 

> I cannot figure out why is this happening.
>> I personally find GWT beeing an easy and very elegant tool for web 
>> development. The Appengine-Datastore-handling part is in my point of view a 
>> real pain in the ass.
>>
>
> JPA and JDO are a PITA, whether or not they're used on AppEngine.
> There are alternatives though (e.g. Objectify).
>

I agree. Maybe Objectify would be a "better" alternative. Unfortunately I 
have 12 Entities which I would need to migrate and to test, and there are 
almost no examples how to use Objectify 4 with the Requestfactory.
 

>
> com.google.web.bindery.event.shared.UmbrellaException: Exception caught: 
>> Server Error 500 <html>
>> <head>
>> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
>> <title>Error 500 Validation failed for 
>> com.emajstor.server.persistence.TestEntity@59778fd8 during pre-update for 
>> groups [interface javax.validation.groups.Default] - exceptions are 
>> attached</title>
>> </head>
>> <body><h2>HTTP ERROR 500</h2>
>> <p>Problem accessing /unAuthRequestFactory. Reason:
>> <pre>    Validation failed for 
>> com.emajstor.server.persistence.TestEntity@59778fd8 during pre-update for 
>> groups [interface javax.validation.groups.Default] - exceptions are 
>> attached</pre></p><h3>Caused by:</h3><pre>*
>> javax.validation.ConstraintViolationException*: Validation failed for 
>> com.emajstor.server.persistence.TestEntity@59778fd8 during pre-update for 
>> groups [interface javax.validation.groups.Default] - exceptions are attached
>>     at 
>> org.datanucleus.validation.BeanValidatorHandler.validate(BeanValidatorHandler.java:71)
>>     at 
>> org.datanucleus.validation.BeanValidatorHandler.preStore(BeanValidatorHandler.java:86)
>>     at 
>> org.datanucleus.api.jpa.JPACallbackHandler.preStore(JPACallbackHandler.java:102)
>>     at 
>> org.datanucleus.state.JDOStateManager.flush(JDOStateManager.java:3827)
>>     at 
>> org.datanucleus.ObjectManagerImpl.flushInternalWithOrdering(ObjectManagerImpl.java:3888)
>>     at 
>> org.datanucleus.ObjectManagerImpl.flushInternal(ObjectManagerImpl.java:3811)
>>     at 
>> org.datanucleus.ObjectManagerImpl.flush(ObjectManagerImpl.java:3751)
>>     at 
>> org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java:4141)
>>     at 
>> org.datanucleus.ObjectManagerImpl.transactionPreCommit(ObjectManagerImpl.java:428)
>>     at 
>> org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:398)
>>     at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:287)
>>     at 
>> org.datanucleus.ObjectManagerImpl.close(ObjectManagerImpl.java:1090)
>>     at 
>> org.datanucleus.api.jpa.JPAEntityManager.close(JPAEntityManager.java:193)
>>     at 
>> com.emajstor.server.AppHandlerFilter.doFilter(AppHandlerFilter.java:91)
>>     at 
>> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
>>
>
> Your OSIV filter is causing a TransactionImpl.commit, which means there's 
> a transaction spanning the entire request (or maybe you have auto-commit 
> enabled, I don't know how JPA/JDO really work).
> That commit triggers validation, and the ConstraintViolationException is 
> shadowing the RequestFactory response (which, if 
> ReflectiveServiceLayer#validate behaved expectedly, would be an 
> onConstraintViolations response)
>

OK .... I see ... YOU ARE RIGHT.
I have tested it using: <property name="datanucleus.NontransactionalWrite" 
value="false"/> I have expected this to prevent non-transactional write as 
you mentioned.
I am getting the following error which lets me think that requestfactory is 
trying to "auto-comit" data into the DB on its own!!

*Am I missing some configurations on GWT level??*


SEVERE: Server error caused 
by:org.datanucleus.exceptions.NucleusUserException
*Cant write fields outside of transactions. You may want to set 
'NontransactionalWrite=true'.*
org.datanucleus.exceptions.NucleusUserException: Cant write fields outside 
of transactions. You may want to set 'NontransactionalWrite=true'.
    at 
org.datanucleus.api.jpa.state.PersistentNontransactional.transitionWriteField(PersistentNontransactional.java:170)
    at 
org.datanucleus.state.AbstractStateManager.transitionWriteField(AbstractStateManager.java:871)
    at 
org.datanucleus.state.JDOStateManager.preWriteField(JDOStateManager.java:3575)
    at 
org.datanucleus.state.AbstractStateManager.setStringField(AbstractStateManager.java:1998)
    at 
com.emajstor.server.persistence.TestEntity.jdoSetmyEmailAddress(TestEntity.java)
    at 
com.emajstor.server.persistence.TestEntity.setMyEmailAddress(TestEntity.java:88)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at 
com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115)
    at 
com.google.web.bindery.requestfactory.server.ReflectiveServiceLayer.setProperty(ReflectiveServiceLayer.java:234)
    at 
com.google.web.bindery.requestfactory.server.ServiceLayerDecorator.setProperty(ServiceLayerDecorator.java:193)
    at 
com.google.web.bindery.requestfactory.server.ServiceLayerDecorator.setProperty(ServiceLayerDecorator.java:193)
    at 
com.google.web.bindery.requestfactory.server.SimpleRequestProcessor$1.visitValueProperty(SimpleRequestProcessor.java:549)
    at 
com.google.web.bindery.autobean.vm.impl.ProxyAutoBean.traverseProperties(ProxyAutoBean.java:289)
    at 
com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.traverse(AbstractAutoBean.java:166)
    at 
com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.accept(AbstractAutoBean.java:101)
    at 
com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.processOperationMessages(SimpleRequestProcessor.java:524)
    at 
com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.process(SimpleRequestProcessor.java:218)
    at 
com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.process(SimpleRequestProcessor.java:135)
    at 
com.google.web.bindery.requestfactory.server.RequestFactoryServlet.doPost(RequestFactoryServlet.java:133)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    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.emajstor.server.AppHandlerFilter.doFilter(AppHandlerFilter.java:72)
    at 
org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    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:123)
    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.DevAppServerServersFilter.doDirectRequest(DevAppServerServersFilter.java:369)
    at 
com.google.appengine.tools.development.DevAppServerServersFilter.doDirectServerRequest(DevAppServerServersFilter.java:352)
    at 
com.google.appengine.tools.development.DevAppServerServersFilter.doFilter(DevAppServerServersFilter.java:115)
    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:97)
    at 
org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at 
com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:480)
    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.content(HttpConnection.java:938)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    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)

 

-- 
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to