Inject resource into Jersey ContainerRequestFilter

时间:2016-10-20 13:24:17

标签: java jersey jax-rs wildfly

I look for way to inject resource in jax-rs (Jersey) filter (ContainerRequestFilter)

This is my filter

@Provider
@Secure
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
    private static final String HEADER_PERFIX = "UUID ";

    @Resource(name = "DataSource")
    private DataSource dataSource;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException { 
        String header = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
        if(header == null || !header.startsWith(HEADER_PERFIX)) {
            requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
        }

        try(Connection connection = dataSource.getConnection()) {

            String query = 
                    "update sessions set expire = now() + interval '1 hour' " + 
                    "where token = ?::uuid";// and expire > now()";

            try(PreparedStatement statement = connection.prepareStatement(query)) {
                String token = header.substring(HEADER_PERFIX.length());
                statement.setString(1, token);

                if(statement.executeUpdate() > 0) {
                    requestContext.setProperty("uuid", token);
                }
                else {
                    requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
                }
            }
        }
        catch(SQLException e) {
            throw new WebApplicationException(e);
        }
    }
}

and web.xml

<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>

    <resource-ref>
        <res-ref-name>DataSource</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>

        <mapped-name>java:jboss/datasources/erp</mapped-name>
    </resource-ref>
</web-app>

in this case dataSource is not null, but with the wrong value (into H2 database). I use wildfly 10.1

Update For now, I use the constructor for manually lookup of resource

@Provider
@Secure
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
    private static final String HEADER_PERFIX = "UUID ";

    private DataSource dataSource;

    public AuthenticationFilter() {
        try {
            dataSource = (DataSource)InitialContext.doLookup("java:comp/env/DataSource");
        }
        catch(NamingException e) {
            dataSource = null;
        }
    }

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException { 
        String header = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
        if(header == null || !header.startsWith(HEADER_PERFIX)) {
            requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
        }

        try(Connection connection = dataSource.getConnection()) {

            String query = 
                    "update sessions set expire = now() + interval '1 hour' " + 
                    "where token = ?::uuid";// and expire > now()";

            try(PreparedStatement statement = connection.prepareStatement(query)) {
                String token = header.substring(HEADER_PERFIX.length());
                statement.setString(1, token);

                if(statement.executeUpdate() > 0) {
                    requestContext.setProperty("uuid", token);
                }
                else {
                    requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
                }
            }
        }
        catch(SQLException e) {
            throw new WebApplicationException(e);
        }
    }
}

UPDATE 2

@Singleton
public class DataSourceProvider {
    @Resource(name = "DataSource")
    private DataSource dataSource;

    @Produces
    @ApplicationScoped
    @Lock(LockType.READ)
    public DataSource getDefualtDataSource() {
        return dataSource;
    }
}

and filter

@Provider
@Secure
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
    private static final String HEADER_PERFIX = "UUID ";

    @Inject
    private DataSource dataSource;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException { 
...

p.s. Sorry for my bad English

1 个答案:

答案 0 :(得分:0)

我建议如下:

1)使用CDI生产者字段使您的数据源@Resource可用作CDI bean。

2)将CDI范围注释(@ApplicationScoped@Dependent)添加到ContainerRequestFilter以将其转换为CDI bean。

然后您应该能够@Inject数据源。

顺便说一句,在Java EE服务器上,不需要使用JDBC连接和预准备语句。请考虑使用EntityManager