简体   繁体   中英

JPA.withTransaction executing other controllers method error: Global.java:39: error: 'void' type not allowed here

I am trying to execute some db insert/update queries in some time intervals.

To achive this I'decided to use Playframework built in Akka Actor system.

I have my class with method:

public class Global extends GlobalSettings {
    @Override
    public void onStart(Application application) {
        Akka.system().scheduler().schedule(
             Duration.create(1, TimeUnit.SECONDS), // start task delay
             Duration.create(24, TimeUnit.HOURS), // between task instance delay
             //Duration.create(24, TimeUnit.HOURS), // between task instance delay
                  new Runnable() {
                      @Override
                      public void run() {
                        JPA.withTransaction(
                            ImportCrmData.start()
                        );
                      }
                  },
                  Akka.system().dispatcher()
        );

And the method that is called by the actor system:

public class ImportCrmData extends Controller {
    @Transactional
    public static void start() {
        List<Customer> customersToUpdate = CustomerCRM.importCrmData();
        for(Customer c: customersToUpdate) {
            c.toDataBase();
        }
    }
}

I am getting an error on compile:

[error] app/modules/common/app/Global.java:39: error: 'void' type not allowed here ImportCrmData.start()

I understand that the problem occurs cause JPA.withTransaction() demand me to return from ImportCrmData.start() return Callback0 or Function0<> , but I dont know how to do it.

My method is just doing this.persist . Why should I even return something from that?

ImportCrmData is a controller thus it must return a valid http response (a result). A typical use case:

public class CustomerController extends Controller {

    public static Result getCustomers() {
        List<Customer> customers = CustomerService.getCustomers();
        return ok(Json.toJson(customers));
    }

}

Above example consists of controller which is an entry point to your application and reacts with client requests. CustomerService encapsulates logic related to getting customers. ok(...) returns an implementation of Result - a valid http response with code 200 and in above scenario, json body. It is implemented in Controller base class. Next your controller can be mapped in routes file to a url like so:

GET /customers controller.CustomerController.getCustomers

Applying above pattern you should have:

  • CrmController - entry point
  • CrmService - actual business logic

This separation allows using your CrmService in Global class, as well as in Controller layer without duplicating logic. Mind this is just a suggestion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM