Вопрос

I am currently in the process of moving business logic from a controller method to a service, when I fell down the rabbit hole of grails services. I have the following method in my service:

Job closeJobOpportunity(Job op, Employee res) {
    op.chosenOne = res
    op.requisitionCanceledDate = new Date() 
    if(!op.chosenOne || !op.hrEffectiveDate){
        return null
    }
    else if(StringUtils.isEmpty(op.chosenOne.id)){
        return null
    }
    return op
}

I started thinking about the different ways this method could cause synchronization problems(because of grails making the service a singleton), and noticed the grails documentation mentions that business logic should be put in the service as long as you don't store the state.

At the risk of sounding ignorant or not well informed, can someone simply provide the differences between stateful and stateless services in Grails? Is the above method stateful? Should it then be surrounded by try catch in the controller?

Это было полезно?

Решение

The difference between stateful and stateless in a Grails service (or any other instance of a class for that matter) is determined by if the instance itself holds any state.

First, it's difficult to say if your Service in your example is stateless or not, but the interaction you have there in that particular method doesn't indicate that you are doing anything stateful with the service itself. That would lead me to believe that the service is going to be stateless.

Let me give you an example of a stateful service and explain why it's stateful.

class MyStatefulService {
  Long someNumber
  String someString

  void doSomething(Long addMe) {
    someNumber += addMe
  }

  void updateSomething(String newValue) {
    someString = newValue
  }
}

As you can see the above service has two properties. If this service is created as a singleton then all calls to it will use the same single instance. As you can see the two methods on the service effect the properties, or state, of the service. This means, in it's current form, you can't be sure that the state doesn't change while a particular thread is executing a method or methods of the service. Making it unreliable, in it's current form. While this is a very simple example it does demonstrate what makes a service stateful.

It's okay for services to have properties, and often they do. They can be references to other services or even configuration values. The key concept is to make sure they don't change state (there is always exceptions to this, but they are the edge cases).

It's entirely possible to rewrite the service to be stateful, synchronized and such to avoid the pitfalls of multiple threads accessing and modifying the state, but it's not something you should aim to do. Stateless services are simpler, cleaner, easier to test, easier to debug, and more lightweight.

In short, make your services stateless and save yourself the headaches.

Другие советы

I agree with the above answer that specifically details stateful vs stateless services. I'd also agree with the process of moving business logic out of the controller layer and avoiding the "fat controller" anti-pattern. However, to answer a slightly different, perhaps implied question, I wouldn't necessary jump to stuffing everything in the service layer.

It does depend on the complexity of your app. In the short term business logic at the service layer is appealing, but I feel like longer term it leads to procedural thinking and code that is hard to extend or reuse. If you're thinking about where actual business logic should live I'd encourage taking 30 minutes and watching this talk.

https://skillsmatter.com/skillscasts/4037-all-hail-the-command-object-are-stateless-services-the-only-way

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top