commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ricardo Gladwell <ricardo.gladw...@btinternet.com>
Subject Re: [configuration] handling exceptions in AbstractConfiguration implementations
Date Wed, 06 Oct 2004 13:30:07 GMT
P.S. Please find the JUnit test code attached.

Ricardo Gladwell wrote:
> Eric Pugh wrote:
> 
>> Hi Ricardo..  Sounds like you are working on something I've been 
>> wanting for
>> a long time!
> 
> 
> Of course, I was going to release it anyway so please find the 
> source-code attached. Not sure it belongs in commons-configration API; 
> probably better contributed to the hibernate project. If you can think 
> of any improvements please mail the patches back to me for my own 
> project :)
> 
>> In otherwords, say I am using a Configuration object in my code, and I do
>> configuration.getDouble("key");.  If getDouble throws an exception 
>> then I am
>> going to have these try/catch cluases all over the place, cluttering the
>> code.  and, I really except getDouble() to allows work.  If it 
>> doesn't, my
>> application will just pass it on,not have some sort of fancy if getDouble
>> fails, then try getString or something weird.
> 
> 
> Good point, although I'm still dubious about throwing RuntimeExceptions 
> - those things shoot straight through everything like a silver bullet 
> and can even crash some servlet engines.
> 
>  From my perspective, I'm not bothered if the Configuration object 
> throws exceptions: I wouldn't catch such exceptions in my web 
> application, instead letting them fly all the way to the exception 
> screen. This way, I can see them occuring as I test my application 
> through the browser.
> 
> Obviously, sometimes when configuring your application you just want 
> your configuration to work or keep on working untill if it encounters an 
> errors. However, simply allowing your application to ignore exceptions 
> until they create new exception elsewhere seems like a good way to 
> create hard-to-fix bugs. Surely, it would be better to relay the errors 
> and let the application decide what to do with them?
> 
>> I think what you can do is just wrap your HibernateException in a
>> ConfiguratoinRuntimeException and toss that.  JDBCConfiguration should
>> probably be doning the same thing.
> 
> 
> Another alternative would be to have a getExceptions() method for all 
> Configurations which stores exceptions occuring and stores them for 
> later reporting. A good comprimise would be to allow all Configuration 
> objects to have two modes: one where exceptions are thrown as soon as 
> they occur and another one which stores exceptions as I suggested.
> 
> Kind regards,
> -- Ricardo Gladwell
> 
>>> -----Original Message-----
>>> From: Ricardo Gladwell [mailto:ricardo.gladwell@btinternet.com]
>>> Sent: Wednesday, October 06, 2004 12:56 PM
>>> To: Jakarta Commons Developers List
>>> Subject: [configuration] handling exceptions in AbstractConfiguration
>>> implementations
>>>
>>>
>>> Hi All,
>>>
>>> I'm currently developing a sub-class of the AbstractConfiguration
>>> classthat uses Hibernate to access configuration properties
>>> (unimaginatively called Hibernate Configuration). I'm slightly concerned
>>> about the way sub-classes are suposed to handle exceptions:
>>>
>>> All the abstract method are defined as not throwing exceptions. All
>>> calls to hibernate, however, throw HibernateExceptions. So, for example,
>>> my implementation of getPropertyDirect calls the hibernate Session.get()
>>> method which can throw an exception.
>>>
>>> Looking at your implementation of the DatabaseConfiguration I can see
>>> that it simply consumes SQLExceptions thrown from the JDBC API, logging
>>> the stack trace. However, what if you want to be warned of exceptions
>>> being thrown by the underlying implementation of Configuration?
>>>
>>> I notice you already have a nestable ConfigurationException implemented.
>>> Surely, all Configuration methods should indicate they will throw this
>>> exception if they are expected to read/write data?
>>>
>>> Also, the AbstractConfiguration class does not describe this contract
>>> (logging all errors throw by underlying framework) or what should be
>>> returned in the event of an error? I assume you should return null
>>> values but this is not described anywhere.
>>>
>>> Kind regards,
>>> -- Ricardo Gladwell
> 
> 
> ------------------------------------------------------------------------
> 
> package net.sf.jexus.server.components;
> 
> import org.apache.commons.logging.Log;
> import org.apache.commons.logging.LogFactory;
> 
> import java.util.Iterator;
> import java.util.List;
> 
> import net.sf.hibernate.HibernateException;
> import net.sf.hibernate.Session;
> import net.sf.hibernate.Transaction;
> import net.sf.jexus.server.data.object.ConfigurationProperty;
> 
> import org.apache.commons.beanutils.ConvertUtils;
> import org.apache.commons.configuration.AbstractConfiguration;
> 
> /**
>  * <p>Hibernate configuation class. Reads configuration infomation from a
>  * database through the <a href="http://www.hibernate.org/">Hibernate</a>
>  * O/R mapping API. Data is stored as name-value pairs, along with the class
>  * information of data stored, using the mapping* defined by the
>  * {@link ConfigurationProperty} POJO hibernate xdoclet directives. Values are
>  * converted to and from strings using 
>  * {@link org.apache.commons.beanutils.ConvertUtils}.</p>
>  * 
>  * @author <a href="mailto:ricardo.gladwell@btinternet.com">Ricardo Gladwell</a>
>  */
> public class HibernateConfiguration extends AbstractConfiguration {
> 
>     /**
>      * Logger for this class
>      */
>     private static final Log log = LogFactory.getLog(HibernateConfiguration.class);
> 
>     /**
>      * Reference to the session factory.
>      */
>     Session session;
> 
>     /**
>      * 
>      */
>     class KeyIterator implements Iterator {
> 
>         Iterator iterator;
>         String last;
> 
>         public KeyIterator(Iterator iterator) throws HibernateException {
>             this.iterator = iterator;
>         }
> 
>         /**
>          * @see java.util.Iterator#hasNext()
>          */
>         public boolean hasNext() {
>             return iterator.hasNext();
>         }
> 
>         /**
>          * @see java.util.Iterator#next()
>          */
>         public Object next() {
>             ConfigurationProperty config = (ConfigurationProperty)iterator.next();
>             String key = config.getName();
>             last = key;
>             return key;
>         }
> 
>         /**
>          * @see java.util.Iterator#remove()
>          */
>         public void remove() {
>             clearProperty(last);
>         }
> 
>     }
> 
>     /**
>      * 
>      */
>     public HibernateConfiguration(Session session) {
>         super();
>         if(log.isTraceEnabled()) log.trace("HibernateConfiguration()");
>         this.session = session;
>     }
> 
>     /**
>      * @see org.apache.commons.configuration.AbstractConfiguration#getPropertyDirect(java.lang.String)
>      */
>     protected Object getPropertyDirect(String key) {
>         if(log.isTraceEnabled()) log.trace("getPropertyDirect("+key+")");
>         ConfigurationProperty config = null;
>         try {
>             config = (ConfigurationProperty) session.get(ConfigurationProperty.class,key);
>         } catch(HibernateException e) {
>             log.error("Error reading congfiguration property=["+key+"]",e);
>             return null;
>         }
>         try {
>             Class clazz = getClass().getClassLoader().loadClass(config.getType());
>             return ConvertUtils.convert(config.getValue(), clazz);
>         } catch(ClassNotFoundException e) {
>             log.warn("Cannot find class=["+config.getType()+"] for property=["+key+"]",e);
>         }
>         return config.getValue();
>     }
> 
>     /**
>      * @see org.apache.commons.configuration.AbstractConfiguration#addPropertyDirect(java.lang.String,
java.lang.Object)
>      */
>     protected void addPropertyDirect(String key, Object value) {
>         if(log.isTraceEnabled()) log.trace("addPropertyDirect("+key+","+value+")");
>         ConfigurationProperty config = new ConfigurationProperty();
>         config.setName(key);
>         config.setValue(ConvertUtils.convert(value));
>         config.setType(value.getClass().getName());
>         try {
>             Transaction transaction = session.beginTransaction();
>             session.save(config);
>             transaction.commit();
>         } catch(HibernateException e) {
>             log.error("Error adding congfiguration property=["+key+"]",e);
>         }
>     }
> 
>     /**
>      * @see org.apache.commons.configuration.Configuration#isEmpty()
>      */
>     public boolean isEmpty() {
>         if(log.isTraceEnabled()) log.trace("isEmpty()");
>         try {
>             List list = session.find("from Configuration");
>             return list.isEmpty();
>         } catch(HibernateException e) {
>             log.error("Error reading keys.",e);
>             return true;
>         }
>     }
> 
>     /***
>      * @see org.apache.commons.configuration.Configuration#containsKey(java.lang.String)
>      */
>     public boolean containsKey(String key) {
>         if(log.isTraceEnabled()) log.trace("containsKey("+key+")");
>         return (getPropertyDirect(key) != null);
>     }
> 
>     /**
>      * @see org.apache.commons.configuration.Configuration#clearProperty(java.lang.String)
>      */
>     public void clearProperty(String key) {
>         if(log.isTraceEnabled()) log.trace("clearProperty("+key+")");
>         ConfigurationProperty config = new ConfigurationProperty();
>         config.setName(key);
>         try {
>             Transaction transaction = session.beginTransaction();
>             session.delete(config);
>             transaction.commit();
>         } catch(HibernateException e) {
>             log.error("Error clearing congfiguration property=["+key+"]",e);
>         }
>     }
> 
>     /**
>      * @see org.apache.commons.configuration.Configuration#getKeys()
>      */
>     public Iterator getKeys() {
>         if(log.isTraceEnabled()) log.trace("getKeys()");
>         try {
>             List list = session.find("from Configuration");
>             return new KeyIterator(list.iterator());
>         } catch(HibernateException e) {
>             log.error("Error reading keys.",e);
>             return null;
>         }
>     }
> 
> }
> 
> 
> ------------------------------------------------------------------------
> 
> /*
>  * Copyright 2004 Ricardo Gladwell
>  *
>  * Licensed under the Apache License, Version 2.0 (the "License");
>  * you may not use this file except in compliance with the License.
>  * You may obtain a copy of the License at
>  *
>  *     http://www.apache.org/licenses/LICENSE-2.0
>  *
>  * Unless required by applicable law or agreed to in writing, software
>  * distributed under the License is distributed on an "AS IS" BASIS,
>  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>  * See the License for the specific language governing permissions and
>  * limitations under the License.
>  */
> 
> package net.sf.jexus.server.data.object;
> 
> /**
>  * Hibernate persistance JavaBean encapsulating information about
>  * a configuration property.
>  * 
>  * @hibernate.class
>  *      table="configuration"
>  * 
>  * @todo Create JUnit test cases.
>  * @author <a href="mailto:ricardo.gladwell@btinternet.com">Ricardo Gladwell</a>
>  * @version $Revision: 1.1 $, $Date: 2004/10/05 14:03:55 $
>  */
> public class ConfigurationProperty {
> 
>     /**
>      * Name of this configuration property.
>      */
>     String name;
> 
>     /**
>      * String representation of the valye of this configuration property.
>      */
>     String value;
> 
>     /**
>      * Fully qualified class for this configuration property's type.
>      */
>     String type;
> 
>     /**
>      * Returns the key name for this configuration property.
>      * 
>      * @hibernate.id
>      *      generator-class="assigned"
>      * 
>      * @return Returns the name.
>      */
>     public String getName() {
>         return name;
>     }
> 
>     /**
>      * Sets the key name for this configuration property.
>      * @param name The name to set.
>      */
>     public void setName(String name) {
>         this.name = name;
>     }
> 
>     /**
>      * Returns the value of this property.
>      * 
>      * @hibernate.property
>      * 
>      * @return Returns the value.
>      */
>     public String getValue() {
>         return value;
>     }
> 
>     /**
>      * Sets the value of this property.
>      * @param value The value to set.
>      */
>     public void setValue(String value) {
>         this.value = value;
>     }
> 
>     /**
>      * Returns the fully qualified class name for the type
>      * of the value for this configuration property.
>      * 
>      * @hibernate.property
>      * 
>      * @return Returns the type.
>      */
>     public String getType() {
>         return type;
>     }
> 
>     /**
>      * Sets the fully qualified class name for the type
>      * of the value for this configuration property.
>      * @param type The type to set.
>      */
>     public void setType(String type) {
>         this.type = type;
>     }
> }
> 
> 
> 
> ------------------------------------------------------------------------
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message