Difference between revisions of "POJO Service Engine"
From Opentaps Wiki
Jump to navigationJump to search (→POJO Service Engine) |
(→POJO Service Engine) |
||
Line 23: | Line 23: | ||
# The invoke method must be a void method with no parameters. | # The invoke method must be a void method with no parameters. | ||
# Instead of returning <tt>ServiceUtil.returnError</tt> when there is a problem with the service, throw [[Domain Driven Architecture#Exceptions|exceptions]] such as <tt>ServiceException</tt> | # Instead of returning <tt>ServiceUtil.returnError</tt> when there is a problem with the service, throw [[Domain Driven Architecture#Exceptions|exceptions]] such as <tt>ServiceException</tt> | ||
+ | |||
+ | You can define more than one service inside the same Java class by using different void methods without parameters. The same Java class should be shared among services that have similar input and output parameters. | ||
Here is a complete example: | Here is a complete example: |
Revision as of 21:45, 11 July 2008
POJO Service Engine
The POJO service engine is designed to allow you to mount your Java service objects directly on to the ofbiz service engine, without having to write a static Java method to call it. To use the POJO service engine, you have to declare your service with service engine XML file, just like for all of the other ofbiz services, but use pojo instead of java as the engine:
<service name="opentaps.invoiceNonPhysicalOrderItems" engine="pojo" location="com.opensourcestrategies.financials.invoice.OrderInvoicingService" invoke="invoiceNonPhysicalOrderItems"> <description>Creates an invoice from the non-physical items on the order. It will invoice from the status in the orderItemStatusId, or if it is not supplied, default to ITEM_PERFORMED. After the invoice is created, it will attempt to change the items' status to ITEM_COMPLETE.</description> <attribute name="orderId" type="String" mode="IN" optional="false"/> <attribute name="orderItemStatusId" type="String" mode="IN" optional="true"/> <attribute name="invoiceId" type="String" mode="OUT" optional="false"/> </service>
Then, you could write your service as a Java class with the following requirements:
- It must extend the base org.opentaps.foundation.service.ofbiz.Service class
- You must have a default constructor which takes no parameters
- For each input parameter defined in your services XML, you must have a set method. The set method must be named "set" plus the name of the variable, with the first letter capitalized. For example, if you have "orderId" as an input parameter of your service, you must have a "setOrderId" method. It can not be "SetOrderId", "setorderid", or "setorderId". This is done intentionally to enforce code consistency.
- Each set method must take one parameter, and it must match the parameter in your services XML. For example, if your services XML specifies "java.util.List", your set method take a single parameter of the java.util.List class, not ArrayList, FastList, LinkedList, etc.
- For each output parameter defined in your services XML, you must define one get method which takes no parameters. The name of the get method must be "get" plus the name of the variable with the first letter capitalized (ie, "getInvoiceId()" for "invoiceId").
- The invoke method must be a void method with no parameters.
- Instead of returning ServiceUtil.returnError when there is a problem with the service, throw exceptions such as ServiceException
You can define more than one service inside the same Java class by using different void methods without parameters. The same Java class should be shared among services that have similar input and output parameters.
Here is a complete example:
public class OrderInvoicingService extends Service { private static final String module = OrderInvoicingService.class.getName(); protected String orderId = null; protected String invoiceId = null; // by default, non-physical order items in this state will be invoiced protected String statusIdForNonPhysicalItemsToInvoice = OrderSpecification.ITEM_STATUS_PERFORMED; public OrderInvoicingService() { super(); } public OrderInvoicingService(Infrastructure infrastructure, User user, Locale locale) throws ServiceException { super(infrastructure, user, locale); } public void setOrderId(String orderId) { this.orderId = orderId; } public String getInvoiceId() { return this.invoiceId; } /** * Set the status id of non-physical order items to be invoiced by invoiceNonPhysicalOrderItems, or * OrderSpecification.ITEM_STATUS_PERFORMED will be used * @param statusId */ public void setOrderItemStatusId(String statusId) { if (statusId != null) { statusIdForNonPhysicalItemsToInvoice = statusId; } } public void invoiceNonPhysicalOrderItems() throws ServiceException { try { // validate that the order actually exists and get list of non-physical OrderRepository orderRepository = new OrderRepository(new Infrastructure(dispatcher), user); Order order = orderRepository.getOrderById(orderId); List<GenericValue> itemsToInvoice = order.getNonPhysicalItemsForStatus(statusIdForNonPhysicalItemsToInvoice); // check if there are items to invoice if (UtilValidate.isEmpty(itemsToInvoice)) { throw new ServiceException("OpentapsError_PerformedItemsToInvoiceNotFound", UtilMisc.toMap("orderId", orderId)); } // create a new invoice for the order items // because of the way createInvoiceForOrder is written (665 lines of code!) we'd have to do some re-factoring before we can add the items to an existing invoice Map tmpResult = getDispatcher().runSync("createInvoiceForOrder", UtilMisc.toMap("orderId", orderId, "billItems", itemsToInvoice, "userLogin", user), 7200, false); // no new transaction if (ServiceUtil.isError(tmpResult)) { throw new ServiceException(ServiceUtil.getErrorMessage(tmpResult)); } // change the status of the order items to COMPLETED order.setItemsStatus(itemsToInvoice, OrderSpecification.ITEM_STATUS_COMPLETED); // set the invoiceId of new invoice created this.invoiceId = (String) tmpResult.get("invoiceId"); } catch (GeneralException ex) { throw new ServiceException(ex) ; } } }