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
答案 0 :(得分:0)
我建议如下:
1)使用CDI生产者字段使您的数据源@Resource
可用作CDI bean。
2)将CDI范围注释(@ApplicationScoped
,@Dependent
)添加到ContainerRequestFilter
以将其转换为CDI bean。
然后您应该能够@Inject
数据源。
顺便说一句,在Java EE服务器上,不需要使用JDBC连接和预准备语句。请考虑使用EntityManager
。