The StorageBackendException is catched two times so that the user see the "500 internal server error" only at the second catch (probably fixes #5).
     1.1 --- a/org/sonews/config/Config.java	Sat May 01 18:51:57 2010 +0200
     1.2 +++ b/org/sonews/config/Config.java	Sun May 09 12:38:46 2010 +0200
     1.3 @@ -128,24 +128,20 @@
     1.4      return val;
     1.5    }
     1.6  
     1.7 -  public String get(int level, String key, String def)
     1.8 +  public String get(int maxLevel, String key, String def)
     1.9    {
    1.10 -    switch(level)
    1.11 +    String val = CommandLineConfig.getInstance().get(key, null);
    1.12 +
    1.13 +    if(val == null && maxLevel <= LEVEL_FILE)
    1.14      {
    1.15 -      case LEVEL_CLI:
    1.16 +      val = FileConfig.getInstance().get(key, null);
    1.17 +      if(val == null && maxLevel <= LEVEL_BACKEND)
    1.18        {
    1.19 -        return CommandLineConfig.getInstance().get(key, def);
    1.20 -      }
    1.21 -      case LEVEL_FILE:
    1.22 -      {
    1.23 -        return FileConfig.getInstance().get(key, def);
    1.24 -      }
    1.25 -      case LEVEL_BACKEND:
    1.26 -      {
    1.27 -        return BackendConfig.getInstance().get(key, def);
    1.28 +        val = BackendConfig.getInstance().get(key, def);
    1.29        }
    1.30      }
    1.31 -    return null;
    1.32 +
    1.33 +    return val != null ? val : def;
    1.34    }
    1.35  
    1.36    @Override
     2.1 --- a/org/sonews/config/FileConfig.java	Sat May 01 18:51:57 2010 +0200
     2.2 +++ b/org/sonews/config/FileConfig.java	Sun May 09 12:38:46 2010 +0200
     2.3 @@ -161,6 +161,7 @@
     2.4     * @param key
     2.5     * @param value
     2.6     */
     2.7 +  @Override
     2.8    public void set(final String key, final String value)
     2.9    {
    2.10      settings.setProperty(key, value);
     3.1 --- a/org/sonews/daemon/NNTPConnection.java	Sat May 01 18:51:57 2010 +0200
     3.2 +++ b/org/sonews/daemon/NNTPConnection.java	Sun May 09 12:38:46 2010 +0200
     3.3 @@ -33,6 +33,7 @@
     3.4  import org.sonews.daemon.command.Command;
     3.5  import org.sonews.storage.Article;
     3.6  import org.sonews.storage.Channel;
     3.7 +import org.sonews.storage.StorageBackendException;
     3.8  import org.sonews.util.Log;
     3.9  import org.sonews.util.Stats;
    3.10  
    3.11 @@ -275,7 +276,17 @@
    3.12      try
    3.13      {
    3.14        // The command object will process the line we just received
    3.15 -      command.processLine(this, line, raw);
    3.16 +      try
    3.17 +      {
    3.18 +        command.processLine(this, line, raw);
    3.19 +      }
    3.20 +      catch(StorageBackendException ex)
    3.21 +      {
    3.22 +        Log.get().info("Retry command processing after StorageBackendException");
    3.23 +
    3.24 +        // Try it a second time, so that the backend has time to recover
    3.25 +        command.processLine(this, line, raw);
    3.26 +      }
    3.27      }
    3.28      catch(ClosedChannelException ex0)
    3.29      {
    3.30 @@ -289,7 +300,7 @@
    3.31          ex0a.printStackTrace();
    3.32        }
    3.33      }
    3.34 -    catch(Exception ex1)
    3.35 +    catch(Exception ex1) // This will catch a second StorageBackendException
    3.36      {
    3.37        try
    3.38        {
     4.1 --- a/org/sonews/storage/impl/JDBCDatabase.java	Sat May 01 18:51:57 2010 +0200
     4.2 +++ b/org/sonews/storage/impl/JDBCDatabase.java	Sun May 09 12:38:46 2010 +0200
     4.3 @@ -52,7 +52,7 @@
     4.4  public class JDBCDatabase implements Storage
     4.5  {
     4.6  
     4.7 -  public static final int MAX_RESTARTS = 3;
     4.8 +  public static final int MAX_RESTARTS = 2;
     4.9    
    4.10    private Connection        conn = null;
    4.11    private PreparedStatement pstmtAddArticle1 = null;
    4.12 @@ -110,13 +110,13 @@
    4.13      {
    4.14        // Load database driver
    4.15        Class.forName(
    4.16 -              Config.inst().get(Config.STORAGE_DBMSDRIVER, "java.lang.Object"));
    4.17 +        Config.inst().get(Config.LEVEL_FILE, Config.STORAGE_DBMSDRIVER, "java.lang.Object"));
    4.18  
    4.19        // Establish database connection
    4.20        this.conn = DriverManager.getConnection(
    4.21 -              Config.inst().get(Config.STORAGE_DATABASE, "<not specified>"),
    4.22 -              Config.inst().get(Config.STORAGE_USER, "root"),
    4.23 -              Config.inst().get(Config.STORAGE_PASSWORD, ""));
    4.24 +        Config.inst().get(Config.LEVEL_FILE, Config.STORAGE_DATABASE, "<not specified>"),
    4.25 +        Config.inst().get(Config.LEVEL_FILE, Config.STORAGE_USER, "root"),
    4.26 +        Config.inst().get(Config.LEVEL_FILE, Config.STORAGE_PASSWORD, ""));
    4.27  
    4.28        this.conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
    4.29        if(this.conn.getTransactionIsolation() != Connection.TRANSACTION_SERIALIZABLE)
     5.1 --- a/org/sonews/storage/impl/JDBCDatabaseProvider.java	Sat May 01 18:51:57 2010 +0200
     5.2 +++ b/org/sonews/storage/impl/JDBCDatabaseProvider.java	Sun May 09 12:38:46 2010 +0200
     5.3 @@ -18,10 +18,12 @@
     5.4  
     5.5  package org.sonews.storage.impl;
     5.6  
     5.7 -import org.sonews.storage.*;
     5.8  import java.sql.SQLException;
     5.9  import java.util.Map;
    5.10  import java.util.concurrent.ConcurrentHashMap;
    5.11 +import org.sonews.storage.Storage;
    5.12 +import org.sonews.storage.StorageBackendException;
    5.13 +import org.sonews.storage.StorageProvider;
    5.14  
    5.15  /**
    5.16   *