Querying a list of jobs on a server using EJBs Inspired by this question, I have a Java Enterprise application running in Glassfish 2.1 and a Java SE client that communicates with the server application.

For this I have a bean that maintains a collection of jobs that is set by the server and the client then asks if his job is in the current list of jobs known to the bean.

I want to ask if this code is good.

The client uses this interface:

import javax.ejb.Remote;
@Remote
public interface GeneratorCancelledRemote {
    public boolean isJobCancelled(String jobId);
}


The server uses this interface:

import java.util.Collection;
import javax.ejb.Local;
@Local
public interface GeneratorCancelledLocal {
    public void setJobs(final Collection&lt;String&gt; jobs);
}


And here's the implementation:

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import javax.ejb.Stateless;
@Stateless
public class GeneratorCancelled implements GeneratorCancelledLocal, GeneratorCancelledRemote {
    private Collection&lt;String&gt;  jobs;
    public void setJobs(final Collection&lt;String&gt; jobs) {
        this.jobs = Collections.synchronizedSet(new HashSet&lt;String&gt;());
        this.jobs.addAll(jobs);
    }
    @Override
    public boolean isJobCancelled(final String jobId) {
        return jobs != null &amp;&amp; jobs.contains(jobId);
    }
}


Obviously access to the collection of jobs has to be synchronized somehow. Is the use of Collections.synchronizedSet the best way to do this? The EJB gurus around here shun on the use of synchronized in an EE context.

I found this (in German), which also explains that synchronized is not allowed in EJB.
Your @Stateless service contains a shared state. It looks weird for me.
You never modify a state of jobs, you always create a new object

this.jobs = Collections.synchronizedSet(new HashSet&lt;String&gt;());


Could you please clarify why ?
From synchronization standpoint you have a race condition in setJobs method, so it should be synchronized.
Now, since your write operation (setJobs method) is protected by the intrinsic lock, all read operations should be also protected by the same lock to ensure data visibility. Make isJobCancelled synchronized too.