Is it possible to have objects stored in a data structure for the duration of an App Server’s uptime? Basically I want an EJB that interfaces with this Data Structure, but does not require a full fledged database solution.
As an example I made this dummy animal object:
package com.test.entities; public class Animal implements java.io.Serializable { private static final long serialVersionUID = 3621626745694501710L; private Integer id; private String animalName; public Integer getId() { // TODO Auto-generated method stub return id; } public void setId(Integer id){ this.id=id; } public String getAnimalName(){ return animalName; } public void setAnimalName(String animalName){ this.animalName=animalName; } }
So here is the EJB Remote Interface:
package com.test.beans; import java.util.Map; import javax.ejb.Remote; import com.test.entities.Animal; @Remote public interface MapBeanRemote { public void addAnimal(Animal a); public void removaAnimal(Integer id); public Animal getAnimalById(Integer id); Map<Integer, Animal> getAllAnimals(); }
Here is the Session Bean:
package com.test.beans; import java.util.ConcurrentHashMap; import java.util.Map; import javax.annotation.PostConstruct; import javax.ejb.Stateless; import com.test.entities.Animal; @Stateless(mappedName='ejb/MapBean') public class MapBean implements MapBeanRemote{ Map<Integer, Animal> animalStore; @PostConstruct public void initialize(){ animalStore = new ConcurrentHashMap<Integer,Animal>(); } @Override public void addAnimal(Animal a) { if(a.getId()!=null){ animalStore.put(a.getId(), a); } } @Override public Animal getAnimalById(Integer id) { return animalStore.get(id); } @Override public void removaAnimal(Integer id) { animalStore.remove(id); } @Override public Map<Integer, Animal> getAllAnimals() { return animalStore; } }
So basically I want any client who wants to manipulate the Animal Map to go through this EJB and have each client accessing the same exact Map of objects.
This example does not work good enough. After a while all of the animals are erased (I’m assuming when the EJB gets replaced from the bean pool) Could this somehow be injected as a resource?
This can be accomplished by putting the Map in a Singleton and accessing this singleton from the beans. That way there is a single instance for all the EJB instances (since they share the same classloader). Different Session beans in different EAR’s would not work though as they would each have their own classloader, but that doesn’t appear to be your scenario.
Your existing usage of ConcurrentHashMap will sufficiently handle most of your cases but you still need synchronization around the addAnimal method since you need the map to be consistent between the two method calls.