Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #38873

Re: Does this make sense?

From Patrick Roemer <sangamon@netcologne.de>
Newsgroups comp.lang.java.programmer
Subject Re: Does this make sense?
Date 2019-04-05 17:43 +0200
Organization news.netcologne.de
Message-ID <q87t34$l7l$1@newsreader4.netcologne.de> (permalink)
References <f9818c55-5eb6-47f8-8ec9-d512861ddee7@googlegroups.com> <q84vam$lri$1@dont-email.me> <c001151d-044c-4d1b-ad88-0efd923e4433@googlegroups.com> <q85699$oq6$1@dont-email.me> <b8961ec3-eac5-45da-aa5d-11144bcae219@googlegroups.com>

Show all headers | View raw


Responding to Eric Douglas:
>      public static String testMethod(final String db_connect_string, final String db_userid, final String db_password, final String dbDriver, final String queryText) throws ClassNotFoundException {
>           Class.forName(dbDriver);
>           Connection conn = null;
>           PreparedStatement ps = null;
>           ResultSet rs = null;
>           try {
>                conn = DriverManager.getConnection(db_connect_string, db_userid, db_password);
>                ps = conn.prepareStatement(queryText, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
>                rs = ps.getResultSet();
>           } catch (final SQLException e) {
>                e.printStackTrace();
>                try {
>                     if (ps != null) {
>                          ps.close();
>                     }
>                     if (conn != null) {
>                          conn.close();
>                     }
>                     conn = DriverManager.getConnection("alternate connect string", db_userid, db_password);
>                     ps = conn.prepareStatement(queryText, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
>                     rs = ps.getResultSet();
>                } catch (final SQLException e1) {
>                     e1.printStackTrace();
>                }
>           }
>           try {
>                while (rs.next()) {
>                     System.out.println(rs.getRow());
>                }
>           } catch (final SQLException e1) {
>                e1.printStackTrace();
>           } finally {
>                try {
>                     rs.close();
>                } catch (final SQLException e) {
>                     e.printStackTrace();
>                     throw new Error("SQL issue");
>                }
>           }
>           if (ps != null) {
>                try {
>                     ps.close();
>                } catch (final SQLException e) {
>                     e.printStackTrace();
>                     if (conn != null) {
>                          try {
>                               conn.close();
>                          } catch (final SQLException e1) {
>                               e1.printStackTrace();
>                               throw new Error("SQL issue");
>                          }
>                     }
>                     throw new Error("SQL issue");
>                }
>           }
>           if (conn != null) {
>                try {
>                     conn.close();
>                } catch (final SQLException e) {
>                     e.printStackTrace();
>                     throw new Error("SQL issue");
>                }
>           }
>           return null;
>      }

So you want to open a DB connection, run a prepared statement and obtain
a result set. If any of these steps fails along the way, you want to
retry these steps against a different DB URL. Once you have the result
set, you want to run code against it and *not* retry upon failure. And
of course you want to close all resources, no matter what code path has
been taken. Does that capture the intent?

This feels somewhat odd. I can imagine retrying against the mirror when
the primary DB isn't reachable. But if the statement/result fetching
fails on a live primary, why should I hope for better results against
the mirror?

Anyway, just going with it, I'd try to extract exception handling
responsibilities to reusable abstractions that can also be tested
standalone.

Assume you implement the following:

@FunctionalInterface
public interface CheckedFunction<I, O, E extends Exception> {
  O apply(I input) throws E;
}

@FunctionalInterface
public interface CheckedSupplier<O, E extends Exception> {
  O get() throws E;
}

public static <I, O, E extends Exception> O tryAlternatives(
    CheckedFunction<I, O, E> op,
    I firstInput,
    I... moreInputs
) throws E { ... }

public class CumulativeResource<T extends AutoCloseable>
    implements AutoCloseable {
  public final T resource;

  public interface CumulativeResourceBuilder<T extends AutoCloseable> {
    <S extends AutoCloseable> CumulativeResourceBuilder<S>
      cumulate(CheckedFunction<T, S, Exception> builder);
    CumulativeResource<T> build() throws Exception;
  }

  public static <T extends AutoCloseable> CumulativeResourceBuilder<T>
    from(CheckedSupplier<T, Exception> factory) { ... }
}

Then your actual code might become this:

CumulativeResource<ResultSet> fetchResult(String dbUrl)
    throws Exception {
  return
    CumulativeResource
      .from(() -> DriverManager.getConnection(dbUrl, user, password))
      .cumulate(c ->
        c.prepareStatement(
          query,
          ResultSet.TYPE_SCROLL_INSENSITIVE,
          ResultSet.CONCUR_READ_ONLY
        )
      )
      .cumulate(PreparedStatement::executeQuery)
      .build();
    }

void runQuery() throws Exception {
  try(CumulativeResource<ResultSet> rsRes =
      tryAlternatives(this::fetchResult, firstDbUrl, secondDbUrl)) {
    ResultSet rs = rsRes.resource;
    while (rs.next()) {
      System.out.println(rs.getRow());
    }
  }
}

Best regards,
Patrick

Back to comp.lang.java.programmer | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Does this make sense? Eric Douglas <e.d.programmer@gmail.com> - 2019-04-04 05:22 -0700
  Re: Does this make sense? Eric Sosman <esosman@comcast-dot-net.invalid> - 2019-04-04 09:03 -0400
    Re: Does this make sense? Eric Douglas <e.d.programmer@gmail.com> - 2019-04-04 07:02 -0700
      Re: Does this make sense? Eric Sosman <esosman@comcast-dot-net.invalid> - 2019-04-04 11:01 -0400
        Re: Does this make sense? Eric Douglas <e.d.programmer@gmail.com> - 2019-04-04 08:21 -0700
        Re: Does this make sense? Eric Douglas <e.d.programmer@gmail.com> - 2019-04-04 11:45 -0700
          Re: Does this make sense? Arne Vajhøj <arne@vajhoej.dk> - 2019-04-04 20:33 -0400
            Re: Does this make sense? Eric Douglas <e.d.programmer@gmail.com> - 2019-04-05 08:39 -0700
              Re: Does this make sense? Arne Vajhøj <arne@vajhoej.dk> - 2019-04-05 12:31 -0400
              Re: Does this make sense? bursejan@gmail.com - 2019-04-05 10:53 -0700
                Re: Does this make sense? bursejan@gmail.com - 2019-04-05 10:57 -0700
                Re: Does this make sense? bursejan@gmail.com - 2019-04-05 11:02 -0700
                Re: Does this make sense? bursejan@gmail.com - 2019-04-05 11:13 -0700
          Re: Does this make sense? Patrick Roemer <sangamon@netcologne.de> - 2019-04-05 17:43 +0200
            Re: Does this make sense? Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2019-04-07 22:14 +0200
      Re: Does this make sense? Andreas Leitgeb <avl@logic.at> - 2019-04-04 15:15 +0000

csiph-web