Difference between revisions of "Java Wrapper for OFBiz Services"

From Opentaps Wiki
Jump to navigationJump to search
m
Line 3: Line 3:
 
These service wrappers can be used instead of raw Maps to set or get the service parameters in a type-safe way. The POJOs are in <tt>org.opentaps.domain.base.services</tt> package and named after the original service definition (converted to a valid java class name.)  For example: ''createInventoryItem'' is ''CreateInventoryItemService'', ''opentaps.runMrp'' is ''OpentapsRunMrpService''.
 
These service wrappers can be used instead of raw Maps to set or get the service parameters in a type-safe way. The POJOs are in <tt>org.opentaps.domain.base.services</tt> package and named after the original service definition (converted to a valid java class name.)  For example: ''createInventoryItem'' is ''CreateInventoryItemService'', ''opentaps.runMrp'' is ''OpentapsRunMrpService''.
  
The main benefit is that each parameter is guarantee to exist and be of the correct type by the compiler. This makes code maintenance much easier if the service definitions are changed.  In addition, an IDE such as Eclipse can help discover the service parameters via autocompletion.  If a service is defined multiple time the wrapper class reflects the actual service definition as seen by the service engine
+
The main benefit is that each parameter is guaranteed to exist and be of the correct type by the compiler. This makes code maintenance much easier if the service definitions are changed.  In addition, an IDE such as Eclipse can help discover the service parameters via autocompletion.  If a service is defined multiple time the wrapper class reflects the actual service definition as seen by the service engine.
  
 
== Calling a service ==
 
== Calling a service ==

Revision as of 05:51, 21 November 2009

Starting with opentaps 1.4 (after preview 2), opentaps will provide Java objects as wrappers for services defined with the ofbiz service engine, including both ofbiz and legacy opentaps services. These "service wrapper POJOs" are automatically generated along with the base entity classes using ant make-base-entities.

These service wrappers can be used instead of raw Maps to set or get the service parameters in a type-safe way. The POJOs are in org.opentaps.domain.base.services package and named after the original service definition (converted to a valid java class name.) For example: createInventoryItem is CreateInventoryItemService, opentaps.runMrp is OpentapsRunMrpService.

The main benefit is that each parameter is guaranteed to exist and be of the correct type by the compiler. This makes code maintenance much easier if the service definitions are changed. In addition, an IDE such as Eclipse can help discover the service parameters via autocompletion. If a service is defined multiple time the wrapper class reflects the actual service definition as seen by the service engine.

Calling a service

For example if there is a service named example with inputs: a String partyId and a BigDecimal amount, and output partyId:

  ExampleService service = new ExampleService();
  service.setInPartytId("somePartyId");
  service.setInAmount(new BigDecimal("40.0"));
  // if the service requires authentication you can either use a User instance
  service.setUser(someUser); // note that this is not setInUser since "user" is not really a defined IN parameter of the service
  // or a GenericValue userLogin instance
  service.setInUserLogin(someUserLogin);
  // calling the service requires an Infrastructure instance
  service.runSync(infrastructure);
  // or it is also possible to specify that a new transaction is not necessary
  service.runSyncNoNewTransaction(infrastructure);
  // getting the service results parameters and status
  if (service.isSuccess()) {
      String exampleOutput = service.getOutPartyId();
  } else if (service.isError()) {
      // getting the service error message
      Debug.logError(service.getErrorMessage(), MODULE);
  }


Calling a service from inside a POJO service can be done using the runSync helper method provided by the Service class:

  ExampleService service = new ExampleService();
  service.setInPartytId("somePartyId");
  service.setInAmount(new BigDecimal("40.0"));
  // this helper method will auto set the current User and Infrastructure
  // and also avoids creating a new transaction
  // on service error, a ServiceException is thrown so there is no need to test for
  // the status in most cases
  runSync(service);
  // at this point the service must have succeeded
  String exampleOutput = service.getOutPartyId();


Using the wrapper inside its service definition

The wrappers can also be used inside the service definition method to read the inputs. Following the same example as above:

  public static Map<String, Object> exampleServiceImplementation(DispatchContext dctx, Map<String, Object> context) {
      ExampleService service = ExampleService.fromInput(context);
      String partyId = service.getInPartyId();
      BigDecimal amount = service.getInAmount();
      // internal parameters are also available
      Locale locale = service.getInLocale();
      TimeZone timezone = service.getInTimeZone();
      // the user is available both as a GenericValue and a User instance
      GenericValue userLogin = service.getInUserLogin();
      User user = service.getUser(); // note that this is not getInUser since "user" is not really a defined IN parameter of the service
      ...
      String resultPartyId = "resultPartyId"; // the actual service implementation
      ...
      // then out parameter can be set in the same wrapper instance
      service.putAllOutput(ServiceUtil.returnSuccess()); // all the methods from ServiceUtil or UtilMessage normally used 
                                                         // to build the output map can be used here, for success / error or failure
      service.setOutPartyId(resultPartyId);
      return service.outputMap();
  }

Static fields

In addition to the accessors to get or set the inputs or outputs parameters, each wrapper defines an In and Out static enum. Following the example from above, you may also refer to the service parameters like this:

  Map<String, Object> input = UtilMisc.toMap(
     ExampleService.In.partyId.getName(), "somePartyId",
     ExampleService.In.amount.getName(), new BigDecimal("40.0"),
     ExampleService.In.userLogin.getName(), someUserLogin);
  
  Map<String, Object> output = dispatcher.runSync(ExampleService.NAME, input);
  String partyId = (String) mapValue.get(ExampleService.Out.partyId.getName());