Evan LaHurd
Evan LaHurd

Reputation: 977

Using @Lock annotation instead of the synchronized keyword

Application Setup (simplified)

I feel like I am pretty familiar with concurrency in Java, but I am relatively new to Java EE and its annotations.

I have a class called DataHandler annotated with @Singleton that performs some business logic for my application. This class is injected into a web service implementation class annotated with @WebService. When one of the web service's methods is called, DataHandler calls the parseFiles() method which parses some files, and stores data inside of DataHandler. Afterwards it makes some calls to getters inside of DataHandler:

@WebService(portName = "portName",
    serviceName = "MyService",
    endpointInterface = "com.myco.MyPortType",
    wsdlLocation = "WEB-INF/wsdl/MyWSDL.wsdl",
    targetNamespace = "targetNamespace")
public class MyServiceImpl implements MyPortType {

@EJB
private DataHandler dataHandler;

@Override
public ResponseType doStuff(RequestType request) {
    // code
    // ....
    dataHandler.parseFiles();
    // ....
    // more code
    Map<String, CustomType> map = dataHandler.getCustomTypeMap();
    Map<String, CustomType2> map2 = dataHandler.getCustomType2Map();
}

Now I also have message-driven bean that receives some data on a topic called UpdateTopic, then converts it into another type and stores it inside of DataHandler:

@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "UpdateTopic")
})
public class UpdateTopicMDB implements MessageListener {

@EJB
DataHandler dataHandler;

@Override
public void onMessage(Message message) {
    try {
        if (message instanceof ObjectMessage) {
            ObjectMessage objMessage = (ObjectMessage) message;
            Serializable data = objMessage.getObject();
            if (data instanceof UpdateType) {
                dataHandler.convertAndStore((UpdateType) data);
            }
        }
    } catch(Exception e) {
        // log Exception
    }
}

I wanted to synchronize the parseFiles() method, the convertAndStore() method, and the two getters so that all data would be up-to-date when accessed.

I simply made all four methods synchronized to achieve this. My understanding is that if the files were in the middle of being parsed and an update comes into the MDB, then the convertAndStore() method would be locked until parseFiles() is done. Likewise, if an update is being converted and stored and the web service is trying to access one of the two maps, it will wait until convertAndStore() is finished. Correct me if I'm wrong on any of that.


My Question

With all of that being said, I just recently read about the @ConcurrencyManagement and @Lock annotations. Instead of synchronizing these four methods. It now seems as though I should just annotate parseFiles() and convertAndStore() with @Lock(LockType.WRITE) since they are modifying the bean's state and the two getters with @Lock(LockType.READ).

Should I do this and avoid using the synchronized keyword altogether? Would there be any use for synchronized (maybe just for synchronized blocks?), or do these annotations replace it now?

Upvotes: 0

Views: 3861

Answers (1)

Everv0id
Everv0id

Reputation: 1980

When you code JavaEE, you should avoid synchronized and any other manual concurrency implementation. Do not create threads and locks. Instead of that use JSR 236 (EE concurrency utilities).

Upvotes: 0

Related Questions