
Woher Access wohl weiß, daß meine Eingabe einfach wertlos ist?
Ob das ein Versuch ist, Datenmüll vorzubeugen?
Darf ich keine Ausdrücke wie Affenarbeit, Hohldreher oder Plinse eingeben?
asadmin create-mbean --user adminuser --name de.isolvedit.config.category.Development de.isolvedit.config.category.Development --attributes SalesOrganisation=1100:DistributionChannel=10: Category=10:ShipCondition=ST:ChangeUser=unknown:Unit=ST: OrderTypeReturnFlag=ZRE: PositionTypeBuy=?:PositionTypeRent=!Anmerkung: attr=value:attr=value ohne Leerzeichen(!)
[DemoBusiness.doSomething()] : start
[ConfigReader.connectConfigListener()] : add to notification listeners...
[ConfigReader.connectConfigListener()] : ...done:
[ConfigReader.getConfig()] : MBean from server
[ConfigReader.getConfig()] : MBean name: user:impl-class-name=de.isolvedit.config.category.Development, name=de.isolvedit.config.category.Development, server=server
[ConfigReader.getConfig()] : unit=ST
[ConfigReader.getConfig()] : shipCondition=ST
[ConfigReader.getConfig()] : positionTypeRent=FASEL
[ConfigReader.getConfig()] : category=10
[ConfigReader.getConfig()] : distributionChannel=10
[ConfigReader.getConfig()] : positionTypeBuy=BLA
[ConfigReader.getConfig()] : orderTypeReturnFlag=ZRE
[ConfigReader.getConfig()] : changeUser=unknown
[ConfigReader.getConfig()] : salesOrganisation=1100
[ConfigReader.handleNotification()] : notification message: config changed sequence: 10
package de.isolvedit.config.category;
public interface ConfigMBean {
public String getSalesOrganisation();
public void setSalesOrganisation(String salesOrganisation);
public String getDistributionChannel();
public void setDistributionChannel(String distributionChannel);
public String getCategory();
public void setCategory(String category);
public String getShipCondition();
public void setShipCondition(String shipCondition);
public String getChangeUser();
public void setChangeUser(String changeUser);
public String getUnit();
public void setUnit(String unit);
public String getOrderTypeReturnFlag();
public void setOrderTypeReturnFlag(String orderTypeReturnFlag);
public String getPositionTypeBuy();
public void setPositionTypeBuy(String positionTypeBuy);
public String getPositionTypeRent();
public void setPositionTypeRent(String positionTypeRent);
}
package de.isolvedit.config.category;
import javax.management.AttributeChangeNotification;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
public abstract class Config extends NotificationBroadcasterSupport implements ConfigMBean {
public static final String CONFIG_CHANGED = "config changed";
// to set attributes use asadmin or glassfish-GUI !!
// the following properties are set to null, if deployed via glassfish!
// further details: http://docs.sun.com/app/docs/doc/820-4336/gbdzi?a=view
protected String category;
protected String changeUser;
protected String distributionChannel;
protected String orderTypeReturnFlag;
protected String positionTypeBuy;
protected String positionTypeRent;
protected String salesOrganisation;
protected String shipCondition;
protected String unit;
private long sequenceNumber = 1L;
// there is no abstract static -> so this is the method to override in subclasses!
public static Config DefaultConfig() {
return null;
};
public synchronized void configChanged() {
Notification n = new AttributeChangeNotification(this, sequenceNumber++, System.currentTimeMillis(),
CONFIG_CHANGED, "*", "String", null, null);
sendNotification(n);
}
public String getSalesOrganisation() {
return salesOrganisation;
}
public void setSalesOrganisation(String salesOrganisation) {
this.salesOrganisation = salesOrganisation;
configChanged();
}
public String getDistributionChannel() {
return distributionChannel;
}
public void setDistributionChannel(String distributionChannel) {
this.distributionChannel = distributionChannel;
configChanged();
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
configChanged();
}
public String getShipCondition() {
return shipCondition;
}
public void setShipCondition(String shipCondition) {
this.shipCondition = shipCondition;
configChanged();
}
public String getChangeUser() {
return changeUser;
}
public void setChangeUser(String changeUser) {
this.changeUser = changeUser;
configChanged();
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
configChanged();
}
public String getOrderTypeReturnFlag() {
return orderTypeReturnFlag;
}
public void setOrderTypeReturnFlag(String orderTypeReturnFlag) {
this.orderTypeReturnFlag = orderTypeReturnFlag;
configChanged();
}
public String getPositionTypeBuy() {
return positionTypeBuy;
}
public void setPositionTypeBuy(String positionTypeBuy) {
this.positionTypeBuy = positionTypeBuy;
configChanged();
}
public String getPositionTypeRent() {
return positionTypeRent;
}
public void setPositionTypeRent(String positionTypeRent) {
this.positionTypeRent = positionTypeRent;
configChanged();
}
}
package de.isolvedit.config.category;
public class Development extends Config {
public static Development DefaultConfig() {
Development config = new Development();
config.setSalesOrganisation("1100");
config.setDistributionChannel("10");
config.setCategory("10");
config.setShipCondition("ST");
config.setChangeUser("unknown");
config.setUnit("ST");
config.setOrderTypeReturnFlag("ZRE");
config.setPositionTypeBuy("?!?");
config.setPositionTypeRent("!??");
return config;
}
}
package de.isolvedit.config.category;
public class Production extends Config {
public static Production DefaultConfig() {
Production config = new Production();
config.setSalesOrganisation("1100");
config.setDistributionChannel("10");
config.setCategory("10");
config.setShipCondition("ST");
config.setChangeUser("uwEE");
config.setUnit("ST");
config.setOrderTypeReturnFlag("ZRE");
config.setPositionTypeBuy("BUY");
config.setPositionTypeRent("RNT");
return config;
}
}
package de.isolvedit.config;
import java.util.Map;
import javax.management.AttributeChangeNotification;
import javax.management.MBeanServerConnection;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import com.sun.appserv.management.base.Util;
import com.sun.enterprise.admin.server.core.jmx.AppServerMBeanServerFactory;
import de.isolvedit.config.category.Config;
public class ConfigReader implements NotificationListener {
public final static String MBEAN_SERVER_DELEGATE = "JMImplementation:type=MBeanServerDelegate";
public final static String MBEAN_UNREGISTERED = "JMX.mbean.unregistered";
/**
* static log4j-logger
*/
private static final Logger LOGGER = Logger.getLogger(ConfigReader.class);
private MBeanServerConnection server = null;
private Config configCache = null;
private boolean useCachedConfig = false; // force update
private boolean connectedToServerAsListener = false;
private ObjectName configObjectName = null;
public ConfigReader(Config defaultConfig) {
this.configCache = defaultConfig;
this.configObjectName = getObjectName();
// connect to glassfish
server = AppServerMBeanServerFactory.getMBeanServerInstance();
}
// for testing purposes only!
public ConfigReader(Config defaultConfig, MBeanServerConnection server) {
this.configCache = defaultConfig;
this.configObjectName = getObjectName();
this.server = server;
LOGGER.addAppender(new ConsoleAppender(new PatternLayout()));
LOGGER.setLevel(Level.ALL);
}
// react on config changes and mbean unregister events
// if attributes changed invalidate cached config (force update on next getConfig call)
// if config mbean is unregistered invalidate listenmode (force reconnect on next getConfig call)
public synchronized void handleNotification(Notification notification, Object handback) {
try {
if (notification instanceof AttributeChangeNotification) {
LOGGER.info("notification message: " + notification.getMessage() + " sequence: "
+ notification.getSequenceNumber());
if (Config.CONFIG_CHANGED.equals(notification.getMessage())) {
useCachedConfig = false; // force update
}
} else if (MBEAN_SERVER_DELEGATE.equals(notification.getSource().toString())
&& MBEAN_UNREGISTERED.equals(notification.getType()) && !server.isRegistered(configObjectName)) {
releaseConfigListener();
}
} catch (Exception e) {
LOGGER.error("caught exception", e);
}
}
// return config
// try to connect config mbean and register as attribute change and unregister listener
// try to read from config mbean else use default/cached version
public Config getConfig(boolean cachedVersion) {
connectConfigListener();
if (cachedVersion || useCachedConfig) {
LOGGER.info("MBean from cache");
} else {
LOGGER.info("MBean from server");
try {
LOGGER.info("MBean name: " + configObjectName);
@SuppressWarnings("unchecked")
Mapproperties = BeanUtils.describe(configCache);
for (String property : properties.keySet()) {
if (!property.equalsIgnoreCase("Class") && !property.equalsIgnoreCase("NotificationInfo")) {
Object value = server.getAttribute(configObjectName, initCap(property));
LOGGER.info(property + "=" + value.toString());
BeanUtils.setProperty(configCache, property, value);
}
}
useCachedConfig = true;
} catch (Exception e) {
LOGGER.error("caught exception", e);
useCachedConfig = false;
}
}
return configCache;
}
public boolean connectConfigListener() {
boolean result = false;
if (!connectedToServerAsListener) {
LOGGER.info("add to notification listeners...");
try {
server.addNotificationListener(configObjectName, this, null, null);
server.addNotificationListener(getMBeanServerDelegateObjectName(), this, null, null);
connectedToServerAsListener = true;
useCachedConfig = false; // force update
LOGGER.info("...done: ");
result = true;
} catch (Exception e) {
LOGGER.warn("...failed: " + e.getMessage());
e.printStackTrace();
result = false;
}
} else {
result = true;
}
return result;
}
public boolean releaseConfigListener() {
boolean result = false;
if (connectedToServerAsListener) {
try {
LOGGER.info("remove from notification listeners...");
if (server.isRegistered(configObjectName)) {
server.removeNotificationListener(configObjectName, this);
}
server.removeNotificationListener(getMBeanServerDelegateObjectName(), this);
LOGGER.info("...done");
result = true;
} catch (Exception e) {
LOGGER.error("...fail", e);
result = false;
}
connectedToServerAsListener = false;
} else {
result = true;
}
return result;
}
public static String initCap(String input) {
if (input == null || input.isEmpty()) {
return input;
}
return input.substring(0, 1).toUpperCase() + input.substring(1);
}
public ObjectName getObjectName() {
try {
return new ObjectName("user:impl-class-name=" + configCache.getClass().getName() + ",name="
+ configCache.getClass().getName() + ",server=server");
} catch (Exception e) {
return null;
}
}
public static ObjectName getMBeanServerDelegateObjectName() {
return (Util.newObjectName(MBEAN_SERVER_DELEGATE));
}
}
package de.isolvedit.business;
import de.isolvedit.config.category.Config;
import de.isolvedit.config.category.ConfigReader;
import de.isolvedit.config.category.Development;
@Stateless
public class DemoBusiness implements DemoBusinessLocal {
private static final Logger LOGGER = Logger.getLogger(ConfigReader.class);
private ConfigReader conf = new ConfigReader(Development.DefaultConfig());
//private ConfigReader conf = new ConfigReader(Production.DefaultConfig());
public String doSomething(){
LOGGER.info("start");
String result = null;
try {
try {
Config config = conf.getConfig(false);
result = config.getSalesOrganisation();
} catch (Exception e) {
LOGGER.error("caught exception", e);
}
} finally {
conf.releaseConfigListener();
}
return result;
}
}