Difference between revisions of "Working with the Domain Driven Architecture"

From Opentaps Wiki
Jump to navigationJump to search
(Messages from Your Services)
Line 31: Line 31:
  
 
====Messages from Your Services====
 
====Messages from Your Services====
 +
 +
Service can return success and error messages to the user.
 +
 +
To return an error message simply throw a '''ServiceException''.
 +
 +
To return a success message, you can use either '''setSuccessMessage''' or '''addSuccessMessage'''. The former is mean to return a single message whereas the later allows you to return a list of messages.
 +
 +
Each method supports localization by using labels that are translated into the user locale, refer to the API for more details.
 +
 +
For example:
 +
<pre>
 +
public void serviceA() throws ServiceException {
 +
    try {
 +
        // perform some modifications ...
 +
        if (some error) {
 +
            // return an error label, the second arguemnt is the context for substitution in the message
 +
            throw new ServiceException("ErrorLabel", null);
 +
        }
 +
    } catch (SomeException e) {
 +
        // generic error that you do not handle are also displayed back to the user
 +
        // some exception are already localized (for example the RepositoryException related to not found entities)
 +
        throw new ServiceException(e);
 +
    }
 +
    setSuccessMessage("SuccessLabel");
 +
}
 +
</pre>
 +
 +
Beware that nested direct service calls can override the success message, if you do not want that be sure to set it as the last instruction of the method.
 +
 +
<pre>
 +
public void serviceB() throws ServiceException {
 +
    // perform some modifications ...
 +
    setSuccessMessage("SuccessLabelB");
 +
}
 +
 +
public void serviceA() throws ServiceException {
 +
    // perform some modifications ...
 +
    setSuccessMessage("SuccessLabelA");
 +
    serviceB();
 +
    // SuccessLabelB has overwritten the success message set
 +
}
 +
</pre>
 +
 +
If you need to return a list of messages use '''addSuccessMessage''', and beware that '''setSuccessMessage''' will overwrite the list.
 +
 +
<pre>
 +
public void serviceB() throws ServiceException {
 +
    // perform some modifications ...
 +
    addSuccessMessage("SuccessLabelB");
 +
}
 +
 +
public void serviceA() throws ServiceException {
 +
    // perform some modifications ...
 +
    addSuccessMessage("SuccessLabelA");
 +
    serviceB();
 +
    // returns [SuccessLabelA, SuccessLabelB]
 +
}
 +
</pre>
  
 
====Working with Entity Field Names====
 
====Working with Entity Field Names====

Revision as of 18:19, 11 December 2008

Here are some tips for working with the Domain Driven Architecture:

Instantiating Services and Repositories

If you have a domain, the easiest way to instantiate a Service or Repository from your domain is to use the instantiateService or instantiateRepository methods, like this:

    public OrderInventoryService getOrderInventoryService() throws ServiceException {
        return instantiateService(OrderInventoryService.class);
    }

This will automatically set up the Infrastructure and User for your Service or Repository.

Documenting your Services

Since your domain Services do not have to be routed through the ofbiz service engine, you should put the documentation in the Java method so that they would show up in the Java docs as well. For example:

   /**
    * Adds a <code>LockboxBatchItemDetail</code> to an existing
<code>LockboxBatchItem</code>.
    * @throws ServiceException if an error occurs
    * @see #setLockboxBatchId required input <code>lockboxBatchId</code>
    * @see #setItemSeqId required input <code>itemSeqId</code>
    * @see #setAmountToApply required input <code>amountToApply</code>
    * @see #setCashDiscount required input <code>cashDiscount</code>
    * @see #setPartyId optional input <code>partyId</code>
    * @see #setInvoiceId optional input <code>invoiceId</code>
    */

Messages from Your Services

Service can return success and error messages to the user.

To return an error message simply throw a 'ServiceException.

To return a success message, you can use either setSuccessMessage or addSuccessMessage. The former is mean to return a single message whereas the later allows you to return a list of messages.

Each method supports localization by using labels that are translated into the user locale, refer to the API for more details.

For example:

public void serviceA() throws ServiceException {
    try {
        // perform some modifications ...
        if (some error) {
            // return an error label, the second arguemnt is the context for substitution in the message
            throw new ServiceException("ErrorLabel", null);
        }
    } catch (SomeException e) {
        // generic error that you do not handle are also displayed back to the user
        // some exception are already localized (for example the RepositoryException related to not found entities)
        throw new ServiceException(e);
    }
    setSuccessMessage("SuccessLabel");
}

Beware that nested direct service calls can override the success message, if you do not want that be sure to set it as the last instruction of the method.

public void serviceB() throws ServiceException {
    // perform some modifications ...
    setSuccessMessage("SuccessLabelB");
}

public void serviceA() throws ServiceException {
    // perform some modifications ...
    setSuccessMessage("SuccessLabelA");
    serviceB();
    // SuccessLabelB has overwritten the success message set
}

If you need to return a list of messages use addSuccessMessage, and beware that setSuccessMessage will overwrite the list.

public void serviceB() throws ServiceException {
    // perform some modifications ...
    addSuccessMessage("SuccessLabelB");
}

public void serviceA() throws ServiceException {
    // perform some modifications ...
    addSuccessMessage("SuccessLabelA");
    serviceB();
    // returns [SuccessLabelA, SuccessLabelB]
}

Working with Entity Field Names

Each base entity has an enumeration listing its fields, and this enumeration is used in the framework API instead of using string literals. This means it is possible to use the IDE autocompletion but also that the resulting code is no longer at risk of resulting in runtime errors due to typos.

For example, when writing condition maps for the repository find methods, the repository provides a map method which allows you to write the map like this:

findOne(Order.class, map(Order.Fields.orderId, "WS10000"));

findList(OrderItemAssoc.class, map(OrderItemAssoc.Fields.orderId, "WS10000", OrderItemAssoc.Fields.orderItemSeqId, "00001"));

It is also used when retrieving distinct field values from a list, like for example:

List<OrderItem> items = findList(OrderItem.class, map(OrderItem.Fields.orderId, "WS10000"));
Set productIdsInOrder = Entity.getDistinctFieldValues(items, OrderItem.Fields.productId);