Domanda

È possibile avere oggetti archiviati in una struttura di dati per la durata del tempo di attività di un App Server? Fondamentalmente voglio un bean che si interfaccia con questa struttura di dati, ma non richiede una soluzione di database completa.

Come esempio ho realizzato questo oggetto animale fittizio:

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;
    }
}

Quindi ecco l'interfaccia EJB Remote :

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();

}

Ecco il bean di sessione:

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;
    }

}

Quindi, fondamentalmente, desidero che qualsiasi cliente che desideri manipolare la mappa animale passi attraverso questo bean e che ogni client acceda alla stessa esatta mappa di oggetti.

Questo esempio non funziona abbastanza bene. Dopo un po 'tutti gli animali vengono cancellati (suppongo che quando il bean verrà sostituito dal pool di bean) questo potrebbe in qualche modo essere iniettato come risorsa?

È stato utile?

Soluzione

Questo può essere realizzato inserendo la Mappa in un Singleton e accedendo a questo singleton dai bean. In questo modo esiste un'unica istanza per tutte le istanze EJB (poiché condividono lo stesso classloader). Diversi bean di sessione in diverse EAR non funzionerebbero, poiché avrebbero ciascuno il proprio classloader, ma questo non sembra essere il tuo scenario.

L'utilizzo esistente di ConcurrentHashMap gestirà in modo sufficiente la maggior parte dei casi, ma è comunque necessario sincronizzare il metodo addAnimal poiché è necessario che la mappa sia coerente tra le due chiamate di metodo.

Altri suggerimenti

Le nuove specifiche EJB 3.1 forniscono un nuovo tipo di bean - Singleton bean - che sono esattamente ciò di cui hai bisogno. L'unica implementazione con supporto parziale di EJB 3.1 che conosco è Apache OpenEJB 3.1. Include i fagioli Singleton ma non li ho ancora usati.

Questo è un bean di sessione senza stato. Come suggerisce il nome, non si dovrebbe contenere alcun tipo di stato in un tale bean. Un contenitore EJB può funzionare con più istanze del bean per soddisfare richieste simultanee. Come si sincronizzano i dati degli elenchi di tutte le istanze? Penso che non ci sia modo di farlo.

La modifica di tale Elenco in un bean di sessione, che ha dimostrato la logica aziendale, a mio avviso viola persino il concetto del livello aziendale. Devi occuparti delle transazioni e della scrittura simultanea da parte tua.

Perché non tieni l'Elenco degli animali sul lato client? Penso che questo sarebbe il modo migliore.

Penso che la cosa migliore sarebbe spostare completamente la struttura di dati dal bean e archiviarla come una struttura di dati statica. Probabilmente hai ragione nel fatto che i tuoi oggetti vengono cancellati perché gli EJB vengono raggruppati.

Nota a seconda di come si implementa l'accesso alla struttura dati di cui molti hanno bisogno per sincronizzare l'accesso per garantire la sicurezza del thread.

Se si desidera mantenere lo stato all'interno del bean, prendere in considerazione la possibilità di esaminare bean di sessione con stato. Inoltre, se volevi vedere quando i bean venivano distrutti, potresti ignorare il metodo ejbremove, dimentico l'annotazione per Java 5.

Karl

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top