web-services - 如何在 Grails 中实现 REST Web 服务同时处理更多请求?

标签 web-services rest grails

我开发了 REST Web 服务,它能够接受一些数据,从数据库中加载用户,稍作更改并将其保存回数据库。

以下是 REST Web 服务的内容:

class RespondentController {
  static allowedMethods = [save: "GET"]
  synchronized def save = {
    Campaign.withTransaction { status ->
       User user = User.get(params['userId'])
       // do some changes in users...
       user.save()
    }
  }
}

问题是当同时有更多请求时。有没有办法改变网络服务,让它同时接受更多的请求(它可能是一些配置的东西)?
2011-12-18 10:28:57,808 [http-8080-5] ERROR errors.GrailsExceptionResolver  - Exception occurred when processing request: [GET] /my-rest-ws/respondent
Stacktrace follows:
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [my.app.User#1]
        at my.app.UserController$_closure1.doCall(RespondentController.groovy:19)
        at my.app.UserController$_closure1.doCall(RespondentController.groovy)
        at java.lang.Thread.run(Thread.java:636)
2011-12-18 10:29:02,625 [http-8080-5] ERROR events.PatchedDefaultFlushEventListener  - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [my.app.User#1]
        at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1792)
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2435)
        at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335)
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635)
        at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115)
        at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
        at org.codehaus.groovy.grails.orm.hibernate.events.PatchedDefaultFlushEventListener.performExecutions(PatchedDefaultFlushEventListener.java:46)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
        at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
        at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
        at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:147)
        at sun.reflect.GeneratedMethodAccessor773.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:188)
        at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
        at org.codehaus.groovy.grails.plugins.orm.hibernate.HibernatePluginSupport$_addTransactionalMethods_closure22.doCall(HibernatePluginSupport.groovy:502)
        at sun.reflect.GeneratedMethodAccessor666.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058)
        at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1070)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:886)
        at groovy.lang.Closure.call(Closure.java:282)
        at org.codehaus.groovy.runtime.metaclass.ClosureStaticMetaMethod.invoke(ClosureStaticMetaMethod.java:59)
        at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:148)
        at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.call(StaticMetaMethodSite.java:88)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
        at my.app.UserController$_closure1.doCall(UserController.groovy:19)

最佳答案

为每个请求创建一个新 Controller ,因此同步操作将无济于事,因为它不被并发用户共享。另外,它是一个闭包(2.0 之前),同步闭包没有任何意义。

如果要阻止对对象的并发编辑,请将其锁定在事务中。创建服务

class UserService {

   void updateUser(long userId, ...) {
      User user = User.lock(userId)
      // do some changes in users...
      user.save()
   }
}

并将其注入(inject)您的 Controller :
class RespondentController {

   def userService

   def save = {
      long userId = params['userId'] as Long
      userService.updateUser(userId, ...)
   }
}

关于web-services - 如何在 Grails 中实现 REST Web 服务同时处理更多请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8551835/

相关文章:

wordpress - 如何让 WordPress 的 REST API 包含用户元数据?

AngularJS 与超媒体 (HATEOAS) : how to use hypermedia urls accross states

grails - Chrome开发人员工具显示Grails应用程序中动态生成的文件的下载状态已取消

grails - Grails 2.0缺陷NoClassDefFound问题

java - Tomcat 中 Web 服务的 Shutdownhook

javascript - AWS 无服务器 Web 应用程序示例

rest - 使用 Elixir 和 HTTPoison 访问 Azure 存储服务 REST API

grails - Grails打开空白页没有错误

java - 两个 Web 服务之间的通信

web-services - 使用 Objective C 进行 SOAP 查询