如何将数据库连接工厂服务注入Jersey应用程序

时间:2016-12-19 22:34:36

标签: java unit-testing dependency-injection jersey

我有一个平针织应用程序,我正在编写用于测试我的dao方法的单元测试,并证明在我的应用程序运行时注入依赖项非常复杂。

这是我的web.xml。你可以看到我使用包扫描

<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
     see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <servlet>
    <servlet-name>myapp</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>my.package.MyApplication</param-value>
    </init-param>
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>
        my.package
      </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>myapp</servlet-name>
    <url-pattern>/api/v1/*</url-pattern>
  </servlet-mapping>
</web-app>

我有一个控制器,它有一个处理URI的方法。这个方法调用我的dao方法,如下所示:

public class Dao {
    // I use a datasource when my app runs on tomcat, but for unit testing I spin up an in memory database and run my unit tests against that. Can't set a datasource for an in memory database
    public static final String DATASOURCE_NAME = "jdbc/myDataSource";

    // Dependency to be injected
    private ConnectionFactory connectionFactory = null;

    public void setConnectionFactory(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }
...

我有一个单元测试,只是这样做:

Dao dao = new Dao();
dao.setConnectionFactory(new DriverManagerConnectionFactory("jdbc:hsqldb:mem:mymemdb:user=SA;"));
...

我可以轻松运行我的单元测试。问题是现在我的应用程序坏了b / c我不知道如何在应用程序启动时或通过URI调用控制器方法时注入我的DataSourceConnectionFactory。

泽西岛的文件遍布各处,模糊不清,并没有提供我能够遵循的任何真实案例。

1 个答案:

答案 0 :(得分:0)

如果您使用的是Jersey 2.x,据我所知,他们可以在此依赖注入泽西资源:https://jersey.java.net/documentation/latest/ioc.html

老实说,对于使用jersey的小型应用程序,我使用工厂滚动自己的依赖注入,而不是使用JSR-330注释或其他DI机制。我的jersey资源构造了一个POJO实例(比如AccountManager)来完成工作,POJO构造函数依赖于它(比如说IAccountDAO),而jersey资源只是去POJO工厂获得依赖。这使得此示例中的AccountManager POJO易于单元测试,因为它在构造函数中提供了DAO而不是直接耦合到一个,不需要DI框架和注释来遍历代码。基本上它仍然是DI但没有框架。我只会为非常小的应用程序执行此操作 - 我只是觉得使用Google Guice或Spring DI打击每个应用程序都有点矫枉过正 - 在这些工具出现之前就存在DI的概念。

以下示例球衣资源。

DependenciesFactory是一个POJO,它为您的环境适当地构建具有依赖关系的类。例如,如果“TeacherDirectory”需要向其注入数据源,或者向其注入DAO,而DAO又注入了数据源,则工厂会处理该数据源。当你这样做时,你必须考虑单身或不单身自己,但这是非常易于管理的。您还经常需要一种方法来告诉您所处的环境 - 或者至少可能是本地开发人员与已部署的环境 - 这对于任何DI也是如此。 DI可以管理多种配置,因此如果您需要多种配置并手动自己动手,则需要处理。

@Path("/teachers")
public class TeacherResource {
    private final ITeacherDirectory teacherDirectory;

    public TeacherResource() {
        this.teacherDirectory = DependenciesFactory.getTeacherDirectory();
    }

    @GET
    @Path("/")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Provider> getTeachers(@QueryParam("teacherId") String teacherId, 
                                       @QueryParam("firstName") String firstName, 
                                       @QueryParam("lastName") String lastName) {

        return this.teacherDirectory.findTeachers(teacherId, firstName, lastName);
    }