2017-06-04 1 views
0

Mon singleton s'appelle Resources. Il ne doit être instanciée une fois par cette norme Singleton je:Singleton est instancié deux fois dans Glassfish Server

package site.kevindhu.models; 
 

 
import site.kevindhu.entity.Player; 
 

 
import java.util.HashMap; 
 
import java.util.HashSet; 
 
import java.util.Map; 
 

 
public class Resources { 
 
    public static Resources resources; 
 
    public Map<String, Object> data; 
 

 
    static { 
 
     resources = new Resources(); 
 
    } 
 

 
    private Resources() { 
 
     data = new HashMap<>(); 
 
     data.put("players", new HashSet<Player>()); 
 
     data.put("newPlayers", new HashSet<Player>()); 
 
    } 
 

 

 
    public static Resources getInstance() { 
 
     return resources; 
 
    } 
 
}

Cependant, il ne fonctionne pas correctement!

Quand je déployez un .ear pour exécuter mon serveur GlassFish, il va dans ce bloc deux fois:

static { 
 
     resources = new Resources(); 
 
    }

En conséquence, la « singleton » crée en fait deux ressources différentes, chacune temps que je cours le serveur.

Je sais que je fais deux fois parce que je débogue il appelle deux objets Ressources différents chaque fois que je tente d'appeler Resources.resources. Est-ce probablement parce que je déploie un fichier .ear? Comment fonctionnent les spécificités de cette double instanciation?

+0

Très probablement votre classe se charge par différents classloaders. En fonction de ce que vous écrivez, un singleton personnalisé comme celui-ci n'est probablement pas la meilleure des idées dans un serveur d'applications. – pvg

+0

Je voudrais également suggérer que c'est un problème de classloader. Y a-t-il plusieurs fichiers WAR dans votre fichier EAR? Chacun aura probablement son propre ClassLoader, et donc une instance distincte de Resources. Voir [cette réponse] (https://stackoverflow.com/a/4132721/3586783) pour un peu plus d'informations. – pacifier21

+0

J'ai effectivement changé mon déploiement en un fichier .war, et cela se produit toujours. –

Répondre

0

La meilleure façon de faire est de laisser le compilateur gérer pour vous:

/** Singleton. */ 
public enum Resources { 
    RESOURCES; 

    private final Map<String, Team> teams = new HashMap<>(); 

    public boolean add(Team team) { 
    return team != null 
     && teams.put(team.getName(), team) == null; 
    } 

    public Team find(String name) { 
    return name == null ? null : teams.get(name); 
    } 

    public Team find(Team team) { 
    return team == null ? null : get(team.getName()); 
    } 

    public Map<String, Team> getTeams() { 
    return Collections.unmodifiableMap(teams); 
    } 

    // remove, iterators, etc. 
} 

public class TeamImpl implements Team { 
    private final String name; 
    private final Map<String, Player> roster = new HashMap<>(); 

    public TeamImpl(String name) { 
    if (name == null) { 
     throw new IllegalArgumentException("name must not be null"); 
    } 
    this.name = name; 
    assert this.name != null; 
    } 

    @Override 
    public boolean equals(Object other) { 
    // base comparison on team name 
    } 

    @Override 
    public int hashCode() { 
    assert this.name != null; 
    return name.hashCode(); 
    } 

    // methods from interface Team: 

    @Override 
    public String getName() { 
    return name; 
    } 

    @Override 
    public Set<Player> getRoster() { 
    return Collections.unmodifiableSet(new HashSet<>(roster.values())); 
    } 

    @Override 
    public boolean add(Player player) { 
    return player != null 
     && roster.put(player.getName(), player) == null; 
    } 

    @Override 
    public Player find(String name) { 
    return name == null ? null : roster.get(name); 
    } 

    // remove, iterators, etc. 
}