I experienced weird things when writing CD using K3B. The verification
always fails when I use cdrecord in DAO mode. I tried RAW mode and
suprprisingly it succeeded.
Wednesday, September 21, 2005
Samsung CD Writer and K3B
Tuesday, September 6, 2005
Found Resin Xml Bug
I've finally fixed bug which plagued my project for some time. The bug causes FileSystemPreferences to throw warning messages like this:
every 30 seconds.
This is happened on Resin 3.0.13. I fixed this by adding the following lines into my resin-web.xml.
The NPE is thrown on the line 321 of java.util.prefs.XmlSupport
Resin xml implementation would behave correctly if item(1) was modified to item(0). After several considerations I decide to stop using resin xml implementation in favor of default JDK 1.4 xml instead of creating my own implementation of Preferences.
Couldn't flush user prefs: java.util.prefs.BackingStoreException: java.lang.NullPointerException every 30 seconds.
This is happened on Resin 3.0.13. I fixed this by adding the following lines into my resin-web.xml.
<system-property
javax.xml.parsers.DocumentBuilderFactory=
"org.apache.crimson.jaxp.DocumentBuilderFactoryImpl"/>
<system-property
javax.xml.parsers.SAXParserFactory=
"org.apache.crimson.jaxp.SAXParserFactoryImpl"/>
The NPE is thrown on the line 321 of java.util.prefs.XmlSupport
319 | Element xmlMap = (Element) doc.getChildNodes().item(1);
returns null ^^^
320 | // check version
321 | String mapVersion = xmlMap.getAttribute("MAP_XML_VERSION");
Resin xml implementation would behave correctly if item(1) was modified to item(0). After several considerations I decide to stop using resin xml implementation in favor of default JDK 1.4 xml instead of creating my own implementation of Preferences.
Thursday, August 25, 2005
Hard Time Working with Webwork's altSyntax
Actually I have hard time working with Webwork's altSyntax. It is %{} that caused me headache. I have to check whether the getValueClassType() return String or not. To me it's inconsistent. I'm more willing to put %{} every where when I need OGNL than checking individual tag;s value class type.
Tuesday, July 26, 2005
Migration to WebWork altSyntax
Today I've just migrated my WebWork application to altSyntax. My IDEA made this job painless. I just replaced with regular expression "'|'" to ". Then I enclosed some parameter values with %{...}. I just realized that hidden, textfield, label, and textarea tags need their value parameter enclosed with %{...} opposed to those of checkbox, checkbox list, radio, and select tags which do not so.
Also, param tags still need the "''" if you want to pass String values.
Also, param tags still need the "''" if you want to pass String values.
Saturday, July 16, 2005
Indonesian IzPack
Today I created an Indonesian translation of IzPack. IzPack is a free installer. I am now submitting this translation to the IzPack team.
Thursday, July 14, 2005
Thinking Of Bug
I was thinking the issues of my JavaBeanAdapter. I think one of the issues is that the inner bean is always regenerated each time the getter was called.
Tuesday, July 12, 2005
Dropping JavaBeanAdapter
I experienced too many issues with JavaBeanAdapter. So, I decided to drop it from my project because I have not enough time to fix it.
Monday, July 11, 2005
POJO Binding
I managed to make JGoodies Binding works with simple POJO. I create JavaBeanAdapter class to do that. Suppose that you have this POJO:
<code>
public class Pojo {
</code>
Then, wrap the POJO:
<code>
That's all. I usually do this in my projects that use JGoodies Binding.
<code>
Here is the complete source code for JavaBeanAdapter.
<code>
package com.katalis.commons.util;
import net.sf.cglib.core.DefaultNamingPolicy;
import net.sf.cglib.core.NamingPolicy;
import net.sf.cglib.core.Predicate;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.commons.beanutils.PropertyUtils;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Java Bean adapter using CGLIB. Adapted from <a href="http://cglib.sourceforge.net/xref/samples/Beans.html">http://cglib.sourceforge.net/xref/samples/Beans.html</a>.
* Adapt POJO to meet JavaBean specification. All generated objects will implement {@link Observable}.
* <p/>
* Expected use of this adapter is as follow:<pre>
* Foo javaBean = JavaBeanAdapter.wrap(new Foo());
* </pre>
* <p/>
* All object graph of the pojo will be wrapped. Exceptions are those of standard java packages.
* <p/>
* Note: Great care must be excercised if you modify the pojo after wrapping. The most obvious is that
* the symetric contract of {@link Object#equals(Object)} will be violated. Example:<pre>
* javaBean.setFoo("foo");
* pojo.setFoo("another");
* javaBean.equals(pojo) //true
* pojo.equals(javaBean) // false
* </pre>
* The safest approach is to use the generated java bean instead.
*
* @author Thomas Edwin Santosa
*/
public class JavaBeanAdapter {
// ------------------------------ FIELDS ------------------------------
private static final Logger log = Logger.getLogger(JavaBeanAdapter.class.getPackage().getName());
private static final Map cache = Collections.synchronizedMap(new WeakHashMap());
private static final InternalCallbackFilter INTERNAL_CALLBACK_FILTER = new InternalCallbackFilter();
private static final NamingPolicy namingPolicy = new JBNamingPolicy();
private static final Class[] INTERFACES = new Class[]{Observable.class};
private Object pojo;
private final PropertyChangeSupport propertySupport;
private final GetterInterceptor getterInterceptor = new GetterInterceptor();
private final SetterInterceptor setterInterceptor = new SetterInterceptor();
private final AddListenerInterceptor addListenerInterceptor = new AddListenerInterceptor();
private final RemoveListenerInterceptor removeListenerInterceptor = new RemoveListenerInterceptor();
private final DelegateInterceptor delegateInterceptor = new DelegateInterceptor();
private final boolean multicast;
// -------------------------- STATIC METHODS --------------------------
/**
* Wrap the pojo using with no multicast .
*
* @param pojo plain old java object
* @return java bean
* @see #wrap(Object, boolean)
*/
public static Object wrap(Object pojo) {
return wrap(pojo, false);
}
/**
* Wrap the pojo. The pojo will be enhanced so that all setters will fire property change support. This method will try
* its best to synchronize the generated java bean's contents with those of the pojo. If that fails, it will log a
* warning.
*
* @param pojo plain old java object
* @param multicast whether the property change event will be multicast or not
* @return JavaBean
* @throws IllegalArgumentException if the pojo have been wrapped already
*/
public static Object wrap(Object pojo, boolean multicast) {
if (Enhancer.isEnhanced(pojo.getClass()) && pojo.getClass().getName().endsWith("JavaBeanAdapter")) {
throw new IllegalArgumentException("The pojo is already wrapped.");
}
Object bean;
IdentitySupport key = new IdentitySupport(pojo);
bean = cache.get(key);
if (bean == null) {
JavaBeanAdapter adapter = new JavaBeanAdapter(pojo, multicast);
Enhancer e = new Enhancer();
e.setSuperclass(pojo.getClass());
e.setNamingPolicy(namingPolicy);
e.setInterfaces(INTERFACES);
e.setCallbacks(
new Callback[]{
adapter.addListenerInterceptor,
adapter.removeListenerInterceptor,
adapter.getterInterceptor,
adapter.setterInterceptor,
adapter.delegateInterceptor
});
e.setCallbackFilter(INTERNAL_CALLBACK_FILTER);
bean = e.create();
try {
PropertyUtils.copyProperties(bean, pojo);
} catch (IllegalAccessException e1) {
log.log(Level.WARNING, "The caller does not have access to the property accessor method.", e1);
} catch (InvocationTargetException e1) {
log.log(Level.WARNING, "The property accessor method throws an exception.", e1);
} catch (NoSuchMethodException e1) {
log.log(Level.WARNING, "an accessor method for this propety cannot be found.", e1);
}
cache.put(key, bean);
}
return bean;
}
private static boolean isSetter(Method method) {
String name = method.getName();
return name.startsWith("set") &&
isVoidAndSingleArgument(method);
}
private static boolean isVoidAndSingleArgument(Method method) {
return method.getParameterTypes().length == 1 && method.getReturnType() == Void.TYPE;
}
private static boolean isNonJavaGetter(Method method) {
String name = method.getName();
boolean possibleGetter = name.startsWith("get") && method.getParameterTypes().length == 0;
if (possibleGetter) {
Class returnType = method.getReturnType();
return !(returnType.isPrimitive() || returnType.isArray() || returnType.getName().startsWith("java"));
}
return false;
}
private static String extractPropertyName(String name) {
char[] propName = name.substring(3).toCharArray();
propName[0] = Character.toLowerCase(propName[0]);
String propNameStr = String.valueOf(propName);
return propNameStr;
}
// --------------------------- CONSTRUCTORS ---------------------------
private JavaBeanAdapter(Object delegate, boolean multicast) {
assert delegate != null : "Delegate must be not null";
pojo = delegate;
propertySupport = new PropertyChangeSupport(delegate);
this.multicast = multicast;
}
// -------------------------- INNER CLASSES --------------------------
private static class IdentitySupport {
private Object object;
IdentitySupport(Object object) {
this.object = object;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof IdentitySupport)) return false;
final IdentitySupport identitySupport = (IdentitySupport) o;
return object == identitySupport.object;
}
public int hashCode() {
return System.identityHashCode(object);
}
}
private class GetterInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
Object retValFromSuper;
Object getterResult = methodProxy.invoke(pojo, objects);
if (getterResult != null && !Enhancer.isEnhanced(getterResult.getClass())) {
retValFromSuper = wrap(getterResult, false);
} else {
retValFromSuper = getterResult;
}
return retValFromSuper;
}
}
private class SetterInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
String name = method.getName();
String propNameStr = null;
Object oldValue = null;
Object newValue = null;
if (!multicast) {
propNameStr = extractPropertyName(name);
if (PropertyUtils.isReadable(pojo, propNameStr)) {
oldValue = PropertyUtils.getProperty(pojo, propNameStr);
}
newValue = objects[0];
}
methodProxy.invoke(pojo, objects);
// we try to minimize the symetric issue
methodProxy.invokeSuper(o, objects);
propertySupport.firePropertyChange(propNameStr, oldValue, newValue);
if (log.isLoggable(Level.FINE)) {
log.fine(name + " called");
}
return null;
}
}
private class AddListenerInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
propertySupport.addPropertyChangeListener((PropertyChangeListener) objects[0]);
return null;
}
}
private class RemoveListenerInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
propertySupport.removePropertyChangeListener((PropertyChangeListener) objects[0]);
return null;
}
}
private class DelegateInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
return methodProxy.invoke(pojo, objects);
}
}
private static class InternalCallbackFilter
implements CallbackFilter {
public int accept(Method method) {
int result;
String name = method.getName();
if ("addPropertyChangeListener".equals(name) && isVoidAndSingleArgument(method)) {
result = 0;
} else if ("removePropertyChangeListener".equals(name) && isVoidAndSingleArgument(method)) {
result = 1;
} else if (isNonJavaGetter(method)) {
result = 2;
} else if (isSetter(method)) {
result = 3;
} else {
result = 4;
}
if (log.isLoggable(Level.FINE)) {
log.fine(method + ":" + result);
}
return result;
}
}
private static class JBNamingPolicy
extends DefaultNamingPolicy {
public String getClassName(String prefix, String source, Object key, Predicate predicate) {
return super.getClassName(prefix, source, key, predicate) + "JavaBeanAdapter";
}
}
}
</code>
Here is the code for Observable:
<code>
package com.katalis.commons.util;
import java.beans.PropertyChangeListener;
/**
* Describes objects that provide bound properties as specified in the
* <a href="http://java.sun.com/products/javabeans/docs/spec.html">Java
* Bean Secification</a>.
*
* @author Karsten Lentzsch
*
* @see java.beans.PropertyChangeListener
* @see java.beans.PropertyChangeEvent
* @see java.beans.PropertyChangeSupport
*/
public interface Observable {
/**
* Adds a <code>PropertyChangeListener</code> to the listener list.
* The listener is registered for all bound properties of this class.
*
* @param listener the PropertyChangeListener to be added
*
* @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
*/
void addPropertyChangeListener(PropertyChangeListener listener);
/**
* Removes a <code>PropertyChangeListener</code> from the listener list.
* This method should be used to remove PropertyChangeListeners that were
* registered for all bound properties of this class.
*
* @param listener the PropertyChangeListener to be removed
*
* @see #addPropertyChangeListener(PropertyChangeListener)
*/
void removePropertyChangeListener(PropertyChangeListener listener);
}
</code>
You will need Commons-Beanutils from Apache Jakarta on the, I forgot the site. You can google them. I think you will need commons-logging as well. Don't forget to add CGLIB!
<code>
public class Pojo {
private String name;}
public void setName(String name) { this.name = name; }
public String getName() { return name; }
</code>
Then, wrap the POJO:
<code>
Pojo javaBean = JavaBeanAdapter.wrap(new Pojo());</code>
That's all. I usually do this in my projects that use JGoodies Binding.
<code>
PresentationModel model = new PresentationModel(JavaBeanAdapter.wrap(new Pojo());</code>
Here is the complete source code for JavaBeanAdapter.
<code>
package com.katalis.commons.util;
import net.sf.cglib.core.DefaultNamingPolicy;
import net.sf.cglib.core.NamingPolicy;
import net.sf.cglib.core.Predicate;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.commons.beanutils.PropertyUtils;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Java Bean adapter using CGLIB. Adapted from <a href="http://cglib.sourceforge.net/xref/samples/Beans.html">http://cglib.sourceforge.net/xref/samples/Beans.html</a>.
* Adapt POJO to meet JavaBean specification. All generated objects will implement {@link Observable}.
* <p/>
* Expected use of this adapter is as follow:<pre>
* Foo javaBean = JavaBeanAdapter.wrap(new Foo());
* </pre>
* <p/>
* All object graph of the pojo will be wrapped. Exceptions are those of standard java packages.
* <p/>
* Note: Great care must be excercised if you modify the pojo after wrapping. The most obvious is that
* the symetric contract of {@link Object#equals(Object)} will be violated. Example:<pre>
* javaBean.setFoo("foo");
* pojo.setFoo("another");
* javaBean.equals(pojo) //true
* pojo.equals(javaBean) // false
* </pre>
* The safest approach is to use the generated java bean instead.
*
* @author Thomas Edwin Santosa
*/
public class JavaBeanAdapter {
// ------------------------------ FIELDS ------------------------------
private static final Logger log = Logger.getLogger(JavaBeanAdapter.class.getPackage().getName());
private static final Map cache = Collections.synchronizedMap(new WeakHashMap());
private static final InternalCallbackFilter INTERNAL_CALLBACK_FILTER = new InternalCallbackFilter();
private static final NamingPolicy namingPolicy = new JBNamingPolicy();
private static final Class[] INTERFACES = new Class[]{Observable.class};
private Object pojo;
private final PropertyChangeSupport propertySupport;
private final GetterInterceptor getterInterceptor = new GetterInterceptor();
private final SetterInterceptor setterInterceptor = new SetterInterceptor();
private final AddListenerInterceptor addListenerInterceptor = new AddListenerInterceptor();
private final RemoveListenerInterceptor removeListenerInterceptor = new RemoveListenerInterceptor();
private final DelegateInterceptor delegateInterceptor = new DelegateInterceptor();
private final boolean multicast;
// -------------------------- STATIC METHODS --------------------------
/**
* Wrap the pojo using with no multicast .
*
* @param pojo plain old java object
* @return java bean
* @see #wrap(Object, boolean)
*/
public static Object wrap(Object pojo) {
return wrap(pojo, false);
}
/**
* Wrap the pojo. The pojo will be enhanced so that all setters will fire property change support. This method will try
* its best to synchronize the generated java bean's contents with those of the pojo. If that fails, it will log a
* warning.
*
* @param pojo plain old java object
* @param multicast whether the property change event will be multicast or not
* @return JavaBean
* @throws IllegalArgumentException if the pojo have been wrapped already
*/
public static Object wrap(Object pojo, boolean multicast) {
if (Enhancer.isEnhanced(pojo.getClass()) && pojo.getClass().getName().endsWith("JavaBeanAdapter")) {
throw new IllegalArgumentException("The pojo is already wrapped.");
}
Object bean;
IdentitySupport key = new IdentitySupport(pojo);
bean = cache.get(key);
if (bean == null) {
JavaBeanAdapter adapter = new JavaBeanAdapter(pojo, multicast);
Enhancer e = new Enhancer();
e.setSuperclass(pojo.getClass());
e.setNamingPolicy(namingPolicy);
e.setInterfaces(INTERFACES);
e.setCallbacks(
new Callback[]{
adapter.addListenerInterceptor,
adapter.removeListenerInterceptor,
adapter.getterInterceptor,
adapter.setterInterceptor,
adapter.delegateInterceptor
});
e.setCallbackFilter(INTERNAL_CALLBACK_FILTER);
bean = e.create();
try {
PropertyUtils.copyProperties(bean, pojo);
} catch (IllegalAccessException e1) {
log.log(Level.WARNING, "The caller does not have access to the property accessor method.", e1);
} catch (InvocationTargetException e1) {
log.log(Level.WARNING, "The property accessor method throws an exception.", e1);
} catch (NoSuchMethodException e1) {
log.log(Level.WARNING, "an accessor method for this propety cannot be found.", e1);
}
cache.put(key, bean);
}
return bean;
}
private static boolean isSetter(Method method) {
String name = method.getName();
return name.startsWith("set") &&
isVoidAndSingleArgument(method);
}
private static boolean isVoidAndSingleArgument(Method method) {
return method.getParameterTypes().length == 1 && method.getReturnType() == Void.TYPE;
}
private static boolean isNonJavaGetter(Method method) {
String name = method.getName();
boolean possibleGetter = name.startsWith("get") && method.getParameterTypes().length == 0;
if (possibleGetter) {
Class returnType = method.getReturnType();
return !(returnType.isPrimitive() || returnType.isArray() || returnType.getName().startsWith("java"));
}
return false;
}
private static String extractPropertyName(String name) {
char[] propName = name.substring(3).toCharArray();
propName[0] = Character.toLowerCase(propName[0]);
String propNameStr = String.valueOf(propName);
return propNameStr;
}
// --------------------------- CONSTRUCTORS ---------------------------
private JavaBeanAdapter(Object delegate, boolean multicast) {
assert delegate != null : "Delegate must be not null";
pojo = delegate;
propertySupport = new PropertyChangeSupport(delegate);
this.multicast = multicast;
}
// -------------------------- INNER CLASSES --------------------------
private static class IdentitySupport {
private Object object;
IdentitySupport(Object object) {
this.object = object;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof IdentitySupport)) return false;
final IdentitySupport identitySupport = (IdentitySupport) o;
return object == identitySupport.object;
}
public int hashCode() {
return System.identityHashCode(object);
}
}
private class GetterInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
Object retValFromSuper;
Object getterResult = methodProxy.invoke(pojo, objects);
if (getterResult != null && !Enhancer.isEnhanced(getterResult.getClass())) {
retValFromSuper = wrap(getterResult, false);
} else {
retValFromSuper = getterResult;
}
return retValFromSuper;
}
}
private class SetterInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
String name = method.getName();
String propNameStr = null;
Object oldValue = null;
Object newValue = null;
if (!multicast) {
propNameStr = extractPropertyName(name);
if (PropertyUtils.isReadable(pojo, propNameStr)) {
oldValue = PropertyUtils.getProperty(pojo, propNameStr);
}
newValue = objects[0];
}
methodProxy.invoke(pojo, objects);
// we try to minimize the symetric issue
methodProxy.invokeSuper(o, objects);
propertySupport.firePropertyChange(propNameStr, oldValue, newValue);
if (log.isLoggable(Level.FINE)) {
log.fine(name + " called");
}
return null;
}
}
private class AddListenerInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
propertySupport.addPropertyChangeListener((PropertyChangeListener) objects[0]);
return null;
}
}
private class RemoveListenerInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
propertySupport.removePropertyChangeListener((PropertyChangeListener) objects[0]);
return null;
}
}
private class DelegateInterceptor
implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
return methodProxy.invoke(pojo, objects);
}
}
private static class InternalCallbackFilter
implements CallbackFilter {
public int accept(Method method) {
int result;
String name = method.getName();
if ("addPropertyChangeListener".equals(name) && isVoidAndSingleArgument(method)) {
result = 0;
} else if ("removePropertyChangeListener".equals(name) && isVoidAndSingleArgument(method)) {
result = 1;
} else if (isNonJavaGetter(method)) {
result = 2;
} else if (isSetter(method)) {
result = 3;
} else {
result = 4;
}
if (log.isLoggable(Level.FINE)) {
log.fine(method + ":" + result);
}
return result;
}
}
private static class JBNamingPolicy
extends DefaultNamingPolicy {
public String getClassName(String prefix, String source, Object key, Predicate predicate) {
return super.getClassName(prefix, source, key, predicate) + "JavaBeanAdapter";
}
}
}
</code>
Here is the code for Observable:
<code>
package com.katalis.commons.util;
import java.beans.PropertyChangeListener;
/**
* Describes objects that provide bound properties as specified in the
* <a href="http://java.sun.com/products/javabeans/docs/spec.html">Java
* Bean Secification</a>.
*
* @author Karsten Lentzsch
*
* @see java.beans.PropertyChangeListener
* @see java.beans.PropertyChangeEvent
* @see java.beans.PropertyChangeSupport
*/
public interface Observable {
/**
* Adds a <code>PropertyChangeListener</code> to the listener list.
* The listener is registered for all bound properties of this class.
*
* @param listener the PropertyChangeListener to be added
*
* @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
*/
void addPropertyChangeListener(PropertyChangeListener listener);
/**
* Removes a <code>PropertyChangeListener</code> from the listener list.
* This method should be used to remove PropertyChangeListeners that were
* registered for all bound properties of this class.
*
* @param listener the PropertyChangeListener to be removed
*
* @see #addPropertyChangeListener(PropertyChangeListener)
*/
void removePropertyChangeListener(PropertyChangeListener listener);
}
</code>
You will need Commons-Beanutils from Apache Jakarta on the, I forgot the site. You can google them. I think you will need commons-logging as well. Don't forget to add CGLIB!
Thursday, July 7, 2005
Binding
Today I'm evaluating JGoodies Binding. I'm impressed on how easy it is. In several hours I get my first hello world come out.
The only problem I face is that the firePropertyChange must be after the change.
This one below won't work in JComboBox
public void setFoo(String foo) {
propertyChangeSupport.firePropertyChange(PROPERTYNAME_FOO, this.foo, foo);
this.foo=foo;
}
But this one works.
public void setFoo(String foo) {
String oldValue = this.foo;
this.foo=foo;
propertyChangeSupport.firePropertyChange(PROPERTYNAME_FOO, oldValue, foo);
}
I don't know why. I suppose Binding does not use the PropertyChangeEvent's new value.
By the way, I use binding 1.0.
The only problem I face is that the firePropertyChange must be after the change.
This one below won't work in JComboBox
public void setFoo(String foo) {
propertyChangeSupport.firePropertyChange(PROPERTYNAME_FOO, this.foo, foo);
this.foo=foo;
}
But this one works.
public void setFoo(String foo) {
String oldValue = this.foo;
this.foo=foo;
propertyChangeSupport.firePropertyChange(PROPERTYNAME_FOO, oldValue, foo);
}
I don't know why. I suppose Binding does not use the PropertyChangeEvent's new value.
By the way, I use binding 1.0.
Wednesday, July 6, 2005
Subscribe to:
Posts (Atom)
