Java 在多项目环境中避免不明确依赖关系的著名策略
我有一个多Maven项目的设置,最终打包为EAR归档。 这些项目属于jar、ejb或war类型 现在我有了一个Java 在多项目环境中避免不明确依赖关系的著名策略,java,jakarta-ee,cdi,glassfish-4,java-ee-7,Java,Jakarta Ee,Cdi,Glassfish 4,Java Ee 7,我有一个多Maven项目的设置,最终打包为EAR归档。 这些项目属于jar、ejb或war类型 现在我有了一个javax.enterprise.context.SessionScopedCDIBean, 注释为javax.enterprise.inject.Default, 携带关于当前用户的信息(主要从Shiro框架中检索)。 我还有两个自治的Web应用程序,它们应该使用这个Bean,所以我把这个Bean放在一个项目中,由两个项目引用 我现在的问题是,我在部署过程中遇到了一个异常,告诉我Bea
javax.enterprise.context.SessionScoped
CDIBean,
注释为javax.enterprise.inject.Default
,
携带关于当前用户的信息(主要从Shiro框架中检索)。
我还有两个自治的Web应用程序,它们应该使用这个Bean,所以我把这个Bean放在一个项目中,由两个项目引用
我现在的问题是,我在部署过程中遇到了一个异常,告诉我Bean不能被注入,因为有两个可能的依赖项,它们指向完全相同的类。
我猜这是因为包含Bean的项目(Jar项目)连接到两个Web项目,并且Bean被多次发现
所以我的问题是:
是否有一种众所周知的策略来处理此类问题,或者有某种方法来向应用服务器/CDI实现发出信号(我的示例中的Glassfish 4.x使用Weld Framework),以便只阅读一次
我确实注意到有可能使用javax.enterprise.inject.Instance
,但我不想使用它,因为允许更改当前操作用户的快照对应用程序至关重要。
我还考虑了通过API和实现项目提供这些Bean的方法,仅将API作为依赖项引用,但这将产生巨大的开销,因为这些项目目前每个只包含一个类
这是我的Beans类标题:
package omega1001.mediaserver.domainmodel.web;
import ...;
@SessionScoped
@Default
public class OmegaMediaServerSubject implements Serializable {
这就是我尝试注入Bean的方式:
@Inject
private OmegaMediaServerSubject subject;
这是我在部署时遇到的例外情况:
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type OmegaMediaServerSubject with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private omega1001.mediaserver.servlet.messageProcessor.DefaultMessageProcessor.subject
at omega1001.mediaserver.servlet.messageProcessor.DefaultMessageProcessor.subject(DefaultMessageProcessor.java:0)
Possible dependencies:
- Managed Bean [class omega1001.mediaserver.domainmodel.web.OmegaMediaServerSubject] with qualifiers [@Default @Any],
- Managed Bean [class omega1001.mediaserver.domainmodel.web.OmegaMediaServerSubject] with qualifiers [@Default @Any]
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:367)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:281)
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:155)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:518)
at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:504)
at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:479)
at org.jboss.weld.bootstrap.WeldStartup.validateBeans(WeldStartup.java:443)
at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:90)
at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:225)
at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:131)
at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:328)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:496)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:539)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:535)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:360)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:534)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:565)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:557)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:360)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:556)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1464)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1300(CommandRunnerImpl.java:109)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1846)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1722)
at org.glassfish.admin.rest.utils.ResourceUtil.runCommand(ResourceUtil.java:253)
at org.glassfish.admin.rest.utils.ResourceUtil.runCommand(ResourceUtil.java:231)
at org.glassfish.admin.rest.utils.ResourceUtil.runCommand(ResourceUtil.java:275)
at org.glassfish.admin.rest.resources.TemplateListOfResource.createResource(TemplateListOfResource.java:133)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:309)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:292)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1139)
at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:375)
at org.glassfish.admin.rest.adapter.RestAdapter$2.service(RestAdapter.java:316)
at org.glassfish.admin.rest.adapter.RestAdapter.service(RestAdapter.java:179)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)
我现在明白了 正如Steve C所指出的: 包含讨论中的Bean的项目与这两个Web项目一起打包 简单的解决方案是将依赖项Maven范围更改为Web项目中提供的依赖项,然后将其作为EAR中的库提供 因此,回答我的问题: 是的,有一个众所周知的策略来处理这类问题,即确保提供包含您的共享bean的项目,但不要将该项目与目标EAR之外的任何其他项目打包 感谢Steve C为您指路 致以最良好的祝愿
J.Adam在我看来,在不同的项目中共享CDI bean不是一个好主意。我更愿意将用户信息重构到一个单独的项目中,例如UserService,它提供了一个清晰的接口(例如JAX-RS),可以被两个web应用程序使用。如果web应用程序是自包含的,不依赖于共享库,那么您将面临较少的问题。这闻起来很像您将包含
OmegaMediaServerSubject
bean的jar内置到EAR中,以及一个或两个WAR文件的web-INF/lib目录中。您需要确保已将maven ear插件配置为生成。@simdevmon您的想法与我的API/Impl方法类似。但正如我所指出的,这将是“巨大的开销,因为这些项目目前每个只包含一个类”。此外,这只是提供用户信息的一个机会。所以我认为这通常是一种有效的方法,但并不完全是我想要的。非常感谢。anyway@SteveC没错,Maven将公共项目与两个Web项目打包在一起。我将验证这是我问题的答案,然后制定一个答案。谢谢你带路。