0

I'm trying to do my first web project using tomcat, jsp, servlets and log4j. I have TO like: User, Subject, Faculty etc, and DAO objects like: UserRepository, SubjectRepository, FacultyRepository etc. With repositories I have the following hierarchy (not all entities placed): repository hierarchy The initialization of DataSource in AbstractRepository goes this way:

public abstract class AbstractRepository<T> implements Repository<T> {

private final static Logger LOG = Logger
        .getLogger(AbstractRepository.class);
private static final DataSource ds = init();

private static  DataSource init() {
    DataSource dataSource = null;
    try {
        Context initContext = new InitialContext();
        dataSource = (DataSource) initContext
                .lookup("java:/comp/env/jdbc/mydb");
    } catch (NamingException ex) {
        LOG.error("Cannot obtain a connection from the pool", ex);
    }
    return dataSource;
}
protected Connection getConnection() throws SQLException {
    return ds.getConnection();
}
....
}

So now if repository needs a Connection its just calls the parent getConnection() method.

The question is it better to have one DataSource object in AbstractRepository and each subclass repository will get Connection using method in parent or each subclass should have its own private final DataSource field which would be initialized in constructor ? Then explain me: if I choose first way should I put on method getConnection synchronized keyword ? And if I choose second way: then subclass repositories should be singletones, because every time the request comes to a servlet it creates some repository and so it will be multiple DataSources? Or Tomcat knows through context.xml file how many Connections it should keep ? I've just got confused. Would you explain the best practices ? Maybe I should re-design something ?

marknorkin
  • 3,904
  • 10
  • 46
  • 82
  • If the `DataSource` is in JNDI, then it probably won't be created every time it's retrieved - it's a singleton. Although that does depend on _how_ you have added it to JNDI. As far as the rest of the questions go, just use DI. Either JavaEE container DI (which you will have to add to Tomcat) or something like Spring. – Boris the Spider Jan 17 '15 at 16:52

1 Answers1

1

I have come across this many times before. I would have a class called CommonDao that is similar to your AbstractRepository. The Connection or DataSource was a variable that belonged to CommonDao, but it was not static... so every instance of CommonDao had their own copy. So my answer is that as long as you do not make AbstractRepository.ds static then you should be fine.

The pros for doing this (having DataSource be part of AbstractRepositor but not be static) is that you have one common way for obtaining your DataSource and can overwrite it if need be by the subclasses (this would require making ds protected).

Jose Martinez
  • 11,452
  • 7
  • 53
  • 68
  • There's a downside on this approach when you have to access to multiple databases, and some of them are not even in the same database engine. – Luiggi Mendoza Jan 17 '15 at 17:13
  • That's not a downside, that's actually one of the reasons why you would go with this approach. Lets say you have a subclass of AbstractRepository that needs to connect to a different DataSource, then it will have the ability to do so because the ds variable is protected and can be overwritten. – Jose Martinez Jan 17 '15 at 17:15
  • @BoristheSpider, agreed. – Jose Martinez Jan 17 '15 at 17:17
  • Or use composition over inheritance and use DI instead of rewriting it for specific classes. I have scenarios where the same domain entity belongs to different data sources, and using this approach won't support it since Java doesn't support multiple inheritance. – Luiggi Mendoza Jan 17 '15 at 17:35
  • 1
    @LuiggiMendoza here is a great article on the pros and cons of DI vs service locator. http://martinfowler.com/articles/injection.html I agree with Martin's assessment that service locator is fine for internal code. I do not know the context of the OP's codes and do not want to re-architect it, just wanted to provide a concise answer to his specific question. – Jose Martinez Jan 17 '15 at 17:47
  • 1
    And a proper answer would be: *it depends*. There's no specific answer unless we know the requirements. – Luiggi Mendoza Jan 17 '15 at 18:14
  • @JoseMartinez thank you for your suggestions. but if i will do datasource static in AbstractRepository - is it will be thread-safe ? or I should put synchronized keyword on getter ? – marknorkin Jan 23 '15 at 21:55
  • @LuiggiMendoza would you also help with thread-safety issue ? is DataSource field thread-safe if I will do it static in abstract class ? or I should use `synchronized` on `getConnection()` ? – marknorkin Jan 23 '15 at 21:58
  • @Mark there won't be any problem if you have a `static final DataSource` field and retrieve connections from there. If a connection is in use, the client will wait until a connection is available. Consider that the `DataSource` **must not** be created several times since each instance of `DataSource` will open several physical connections and some database engines may disallow opening many connections for a single client (the client in this case is your pc). – Luiggi Mendoza Jan 23 '15 at 22:37
  • Mark, @LuiggiMendoza, please do not use static DataSource in an abstract object like this. Because it is abstract that means it may be a parent class to many other classes. By making it static you are forcing all those classes to use the same DataSource, which may not be the case. As far as whether it is thread safe that would be determined by the underlying connection pool or JDBC library that is implementing that DataSource. If it is a connection pool than obviously it will be thread safe. – Jose Martinez Jan 25 '15 at 00:45
  • @Mark, check out this question about DataSource and thread safe... http://stackoverflow.com/questions/14872685/is-javax-sql-datasource-thread-safe – Jose Martinez Jan 25 '15 at 00:48
  • I've never said that it's right to associate the datasource to your class. That's since my first comment – Luiggi Mendoza Jan 25 '15 at 01:00
  • @LuiggiMendoza, oh ok I thought you were saying that because you wrote back "Mark there won't be any problem if you have a static final DataSource field and retrieve connections from there". I must have misunderstood what you were implying by that. – Jose Martinez Jan 25 '15 at 01:03
  • @JoseMartinez would you explain how to test such dao (not static) with junit. how to get datasource connection's for testing ? please produce some code sample or useful link to read – marknorkin Feb 04 '15 at 23:08
  • One way (out of many ways) is to have your Dao's use a DataSourceFactory (this is ur own class) to get your DataSource's. I would not have them get them from the InitialContext directly. The factory would have methods for getting and setting DataSource's. If the factory has a DataSource then it will provide upon getting a get request for one, else it would retrieve it itself from the InitialContext and cache it. The factory would have a HashMap to store the DataSources. Your unit tests would populate the factory with mock DataSource that are constructed using Mockito. – Jose Martinez Feb 05 '15 at 03:58
  • @JoseMartinez Thank you for answer. At the moment I'm trying to do more simpler then you desscribed. I found recently this article: https://blogs.oracle.com/randystuph/entry/injecting_jndi_datasources_for_junit . but I can't confugure that code for my purposes. – marknorkin Feb 07 '15 at 10:15
  • @LuiggiMendoza would you also describe how to test my dao's ? At the moment I'm trying to run DataSource outside of the container with no success. How should I configure this code sample for my purposes: https://blogs.oracle.com/randystuph/entry/injecting_jndi_datasources_for_junit ? – marknorkin Feb 07 '15 at 10:18
  • @JoseMartinez I've create a question for it: http://stackoverflow.com/questions/28381396/how-to-test-dao-with-datasource-in-java-web-application/28381745#28381745 . Please follow the link – marknorkin Feb 07 '15 at 11:58
  • @LuiggiMendoza I've create a question for it: http://stackoverflow.com/questions/28381396/how-to-test-dao-with-datasource-in-java-web-application/28381745#28381745 . Please follow the link – marknorkin Feb 07 '15 at 12:14
  • Ok i'll post an answer over there. I think what you want to do can be done using the InitialContext#bind. Let me test it first. – Jose Martinez Feb 07 '15 at 15:09