REST JAX-RSを使用したWebサービスJavaの実装)を知っていると、次の問題が発生しました。リソースクラスの1つにアクセスが必要ですStorageEngine
インターフェースの背後で抽象化されたストレージバックエンドに。現在のStorageEngine
インスタンスをRESTリクエストを処理するリソースクラスに挿入したいこれを行うには、@Context
アノテーションと適切なContextResolver
クラスを使用するのが良い方法だと思いました。
MyResource.Java
:
class MyResource {
@Context StorageEngine storage;
[...]
}
StorageEngineProvider.Java
:
@Provider
class StorageEngineProvider implements ContextResolver<StorageEngine> {
private StorageEngine storage = new InMemoryStorageEngine();
public StorageEngine getContext(Class<?> type) {
if (type.equals(StorageEngine.class))
return storage;
return null;
}
}
私はcom.Sun.jersey.api.core.PackagesResourceConfig
を使用して、プロバイダーとリソースクラスを自動的に検出し、ログによると、StorageEngineProvider
クラスを適切に取得しています(タイムスタンプと不要なものは意図的に省略されています)。
INFO: Root resource classes found:
class MyResource
INFO: Provider classes found:
class StorageEngineProvider
ただし、私のリソースクラスのstorage
の値は常にnull
です。StorageEngineProvider
のコンストラクターもそのgetContext
メソッドもJerseyから呼び出されることはありません。ここで何が悪いのですか?
私はあなたが望むことをするためのJAX-RS固有の方法はないと思います。最も近いのは次のことです:
@Path("/something/")
class MyResource {
@Context
javax.ws.rs.ext.Providers providers;
@GET
public Response get() {
ContextResolver<StorageEngine> resolver = providers.getContextResolver(StorageEngine.class, MediaType.WILDCARD_TYPE);
StorageEngine engine = resolver.get(StorageEngine.class);
...
}
}
ただし、@ javax.ws.rs.core.Contextアノテーションとjavax.ws.rs.ext.ContextResolverは、実際にはJAX-RSに関連し、JAX-RSプロバイダーをサポートする型用であると思います。
Java Context and Dependency Injection(JSR-299)の実装(Java EE 6)で利用可能でなければならない)または他の依存性注入フレームワークを探す必要があるかもしれませんここであなたを助けるためにGoogle Guiceのような。
InjectableProvider を実装します。ほとんどの場合、PerRequestTypeInjectableProviderまたはSingletonTypeInjectableProviderを拡張します。
@Provider
public class StorageEngineResolver extends SingletonTypeInjectableProvider<Context, StorageEngine>{
public MyContextResolver() {
super(StorageEngine.class, new InMemoryStorageEngine());
}
}
あなたにさせます:
@Context StorageEngine storage;
別の方法を見つけました。私の場合、パーシステンスレイヤーからユーザーエンティティとして現在ログインしているユーザーを提供します。これはクラスです:
@RequestScoped
@Provider
public class CurrentUserProducer implements Serializable, ContextResolver<User> {
/**
* Default
*/
private static final long serialVersionUID = 1L;
@Context
private SecurityContext secContext;
@Inject
private UserUtil userUtil;
/**
* Tries to find logged in user in user db (by name) and returns it. If not
* found a new user with role {@link UserRole#USER} is created.
*
* @return found user or a new user with role user
*/
@Produces
@CurrentUser
public User getCurrentUser() {
if (secContext == null) {
throw new IllegalStateException("Can't inject security context - security context is null.");
}
return userUtil.getCreateUser(secContext.getUserPrincipal().getName(),
secContext.isUserInRole(UserRole.ADMIN.name()));
}
@Override
public User getContext(Class<?> type) {
if (type.equals(User.class)) {
return getCurrentUser();
}
return null;
}
}
私はimplements ContextResolver<User>
と@Provider
のみを使用して、Jax-Rsがこのクラスを検出し、SecurityContext
を挿入しました。現在のユーザーを取得するには、修飾子@CurrentUser
でCDIを使用します。したがって、現在のユーザーが必要なすべての場所で、次のように入力します。
@Inject
@CurrentUser
private User user;
本当に
@Context
private User user;
機能しません(ユーザーがnull)。
私のために働くパターン:注入する必要があるオブジェクトを提供するApplicationサブクラスにいくつかのフィールドを追加します。次に、抽象基本クラスを使用して「注入」を行います。
public abstract class ServiceBase {
protected Database database;
@Context
public void setApplication(Application app) {
YourApplication application = (YourApplication) app;
database = application.getDatabase();
}
}
データベースにアクセスする必要のあるすべてのサービスがServiceBaseを拡張し、保護フィールド(または、必要に応じてゲッター)を介してデータベースを自動的に使用できるようになります。
これは、UndertowとResteasyで私に役立ちます。理論的には、アプリケーションのインジェクションは標準のAFAICSでサポートされているため、これはすべてのJAX-RS実装で機能します必要がありますが、他ではテストしていません設定。
私にとって、Bryantのソリューションに対する利点は、データベースのようなアプリケーションスコープのシングルトンを取得できるように、リゾルバークラスを記述する必要がないことです。
誰かがResteasyを使用している場合、これは私にとってうまくいきました。
このようなものを追加した場合:
ResteasyContext.pushContext(StorageEngine.class, new StorageEngine());
jaxrsフィルターのようなものに、それはあなたがこのようなことをすることを可能にします:
@GET
@Path("/some/path")
public Response someMethod(@Context StorageEngine myStorageEngine) {
...
}
これは、SingletonTypeInjectableProvider
のようなものがないResteasyに固有です。