2009-07-19 5 views
0

Je travaille contre la date limite et je transpire maintenant. Depuis quelques jours, je travaille sur un problème et maintenant il est temps de crier.Impossible d'accéder aux données d'instance d'une classe Singleton à partir de MBean

J'ai une application (appelons-la "APP") et j'ai un MBean "PerformanceStatistics" écrit pour APP. J'ai aussi une classe Singleton Data (appelons-la "SDATA") qui fournit des données pour que le MBean accède et calcule certaines choses à l'exécution de l'application. Ainsi, pendant le démarrage de l'application et ensuite dans le cycle de vie de l'application, j'ajouterai des données à l'instance SDATA. Ainsi, cette instance SDATA a toujours les données.

Maintenant, le problème est que je ne suis pas en mesure d'accéder à l'une des données ou des structures de données du MBean PerformanceStatistics. si je vérifie les structures de données lorsque j'ajoute les données, toutes les structures contiennent des données. Mais quand j'appelle cette instance singleton du MBean, je suis en train d'avoir les données vides.

Quelqu'un peut-il expliquer ou avoir des indices sur ce qui se passe? Toute aide serait appréciée.

J'ai essayé toutes sortes de classe SDATA étant finale et toutes les méthodes étant synchronisées, statiques, etc., juste pour m'assurer. Mais pas de chance jusqu'à maintenant. Une autre chose regrettable est que, parfois, j'obtiens différentes instances "ServicePerformanceData" (c'est-à-dire lorsque j'imprime le ServicePerformanceData.getInstance(), elles sont différentes à des moments différents). Je ne suis pas sûr de ce qui se passe. Je cours cette application dans le serveur WebLogic et en utilisant le JConsole.

classe SDATA avec des méthodes d'accès unique tonne et les données

public class ServicePerformanceData { 

private Hashtable<String, ServiceExecutionDataCollector> serviceExecutionDataMap = new Hashtable<String, ServiceExecutionDataCollector>(); 
private HashMap<ServiceExecutionType, String> serviceTypeCountMap = new HashMap<ServiceExecutionType, String>(); 
private HashSet<String> serviceNameSet = new HashSet<String>(); 

private static final long DEFAULT_COUNT = 1; 
private static final ServicePerformanceData INSTANCE = new ServicePerformanceData(); 
private Object SYNC = new Object(); 

private ServicePerformanceData() { 
    // don't allow anyone to instantiate this class 
} 

// clearly this must be a singleton 
public static ServicePerformanceData getInstance() { 
    return INSTANCE; 
} 

public void add(ServiceExecutionDataCollector data) { 
    // I just add some runtime information to the data structures in this INSTANCE 
    synchronized (SYNC) { 
     if (INSTANCE.serviceTypeCountMap.containsKey(data.getServiceType())) { 
      String count = INSTANCE.serviceTypeCountMap.get(data.getServiceType()); 
      INSTANCE.serviceTypeCountMap.put(data.getServiceType(), Integer.toString(Integer.parseInt(count) + 1)); 
     } else { 
      INSTANCE.serviceTypeCountMap.put(data.getServiceType(), Integer.toString(1)); 
     } 

     INSTANCE.serviceExecutionDataMap.put(data.getServiceName(), data); 
     INSTANCE.serviceNameSet.add(data.getServiceName()); 
    } 
} 

public int getServiceTypeCount(ServiceExecutionType type) { 
    if (INSTANCE.serviceTypeCountMap.containsKey(type)) { 
     return Integer.parseInt(INSTANCE.serviceTypeCountMap.get(type)); 
    } 
    return 0; 
} 

public Set getNameList() { 
    return INSTANCE.serviceNameSet; 
} 

// I am copying all the data just to make sure that data structures have data 
public void copyAllMasterData() { 
    synchronized (SYNC) { 
     serviceExecutionDataMap.putAll(ServicePerformanceData.INSTANCE.serviceExecutionDataMap); 
     serviceNameSet.addAll(ServicePerformanceData.INSTANCE.serviceNameSet); 
     serviceTypeCountMap.putAll(ServicePerformanceData.INSTANCE.serviceTypeCountMap); 
    } 
} 

}

PerformanceStatistics MBean classe Quand j'appelle les données comme ServicePerformanceData .getInstance(), j'ai rien dans cette structure. Donc je ne peux pas obtenir de résultat avec ça.

public class PerformanceStatistics 
    implements PerformanceStatisticsMBean { 

public void completeExecutionDump() { 
    // 
} 


public int getexecuteSSCount() { 
    return ServicePerformanceData.getInstance().getServiceTypeCount(ServiceExecutionType.ADD); 
} 

public String executionInfo(String serviceName) { 
    // GIVES EMPTY LIST EVEN THOUGH THE ACTUAL instance HAS THE DATA 
    return ServicePerformanceData.getInstance().getExecutionInfo(serviceName.trim()); 
} 

public String calledServicesArray() { 
    // servicePerformanceData DOES NOT CONTAIN ANY DATA EVEN THOUGH THE ACTUAL instance HAS THE DATA 
    ServicePerformanceData servicePerformanceData = ServicePerformanceData.getInstance(); 
    servicePerformanceData.copyAllMasterData(); 

    System.out.println("ServicePerformanceData.INSTANCE" + ServicePerformanceData.getInstance()); 
    System.out.println(servicePerformanceData); 

// GIVES EMPTY LIST EVEN THOUGH THE ACTUAL instance HAS THE DATA 
    System.out.println("Name List" + ServicePerformanceData.getInstance().getNameList()); 

    return ServicePerformanceData.getInstance().getNameList().toString(); 
} 

}

Répondre

0

Après beaucoup de recherches et en regardant attentivement le design, cela semble être un problème avec les chargeurs de classe Weblogic. Mon produit a 6 applications différentes et il n'est pas garanti que le même chargeur d'appels charge toutes les applications.

Ainsi, dans le cas ci-dessus, les données réelles sont mises à jour dans une classe chargée par ClassLoader_X et l'accès est effectué par la classe avec ClassLoader_Y. Clairement, les données ne sont pas transparentes entre les chargeurs de classe. Donc, j'ai toujours les différentes instances de la même classe et les données de la classe accesseur sont toujours vides.

Une fois que j'ai déplacé à la fois les classes de création et de consommation de données vers une seule application/Jar, tout fonctionne bien. Je n'ai pas changé le code ci-dessus.

0

pourrait-il que la classe est chargée à partir des chargeurs de classe?

0

D'abord supprimer tous les "INSTANCE". : tu n'en as pas besoin. serviceNameSet = INSTANCE.serviceNameSet = ServicePerformanceData.INSTANCE.serviceNameSet: c'est la même chose. Ensuite, vous vous rendrez compte que votre méthode copyAllMasterData ne fait rien. Il prend juste les éléments d'un ensemble et les met dans le même ensemble. Le seul endroit où vous placez des données dans vos ensembles (serviceNameSet par exemple) est dans la méthode add et je ne le vois pas (méthode add) appelé n'importe où.

Questions connexes