Wiki Spaces

Documentation
Projects
Resources

Get Help from Others

Q&A: Ask OpenMRS
Discussion: OpenMRS Talk
Real-Time: IRC Chat | Slack

Documentation

Page tree
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

Programming to Interfaces

All of our services are interfaces. The default implementation of these services are named *ServiceImpl.java. The implementations can be found in the impl directory of the package.

In order to create a new implementation of a service (for whatever unknown reason that would be in the future), we would only need to change the file specified in Spring's /metadata/api/spring/application-context.xml file.

Context Singleton vs a Context Object

Services are accessed in a static way from the org.openmrs.api.context.Context object:

UserService userService = Context.getUserService();
User = userService.findUser("bob");

The Context object has two primarily goals. Serve up the OpenMRS services (found in the ServiceContext) and serve up the actions for the current user via the UserContext. The UserContext has been extracted out of the Context. The Context and ServiceContext (and hence the services inside of it) remain as singletons while the small UserContext is duplicated for each user that is currently logged in.

Authentication and Authorization

Users are authenticated against the Context in a static way.

Context.authenticate("bob", "password");

The current user's information is stored on the current thread. For the webapp, we have a special problem. Every request to the server is potentially on a new thread. Our custom filter wraps every request. It stores the user's UserContext on the user's session. Before each request the userContext is taken off the session and placed on the thread. After the entire request is complete, the userContext is removed from the thread (and placed back on the session).

Authorization is done through annotations on the interface:

@Transactional
public interface UserService
...
@Authorized({"View Users"})
void List<User> getUsers(Integer userId);
...

Sessions and Transactions

Spring manages our transactions.

All calls within a session are considered to be on one transaction. If an error is encountered all calls are rolled back and an error is returned.

Within the webapp, a session is determined by Spring's OpenSessionInViewFilter. Every request is wrapped with an open session and close session. This is identical to how we were operating under the old api. The only difference now is that that session is now one single transaction.

Outside the webapp, a session should be wrapped with calls to Context.openSession() and Context.closeSession().

To wrap a service within a transaction we use annotations on the interface:

@Transactional
public Interface BensNewService {
 ...

and/or

...
@Transactional(readOnly=true)
public List<BensObject> getBensObjects();
...
  • No labels