Java UnsatisfiedDependencyException: SystemInjecteeImpl 中没有可注入的对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36889504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 18:45:37  来源:igfitidea点击:

UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl

javadependency-injectionjerseyglassfishhk2

提问by J.Olufsen

There are errors when using DI in Jersey Rest application:

在 Jersey Rest 应用程序中使用 DI 时出现错误:

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=PricingService,parent=PricingResource,qualifiers={},position=0,optional=false,self=false,unqualified=null,1633188703)

I am quite new to the concept and it appears quite complicated since there are some examples seems to be deprecated. As I understand there are a few ways to make DI work: native HK2, Spring/HK2 Bridge. What is easier and more straightforward to configure? How to set up programmatically (not a fan of XML) for Jersey 2.x?

我对这个概念很陌生,它看起来很复杂,因为有些示例似乎已被弃用。据我了解,有几种方法可以使 DI 工作:本地 HK2、Spring/HK2 Bridge。什么配置更简单、更直接?如何以编程方式(不喜欢 XML)为 Jersey 2.x 设置?

ResourceConfig

资源配置

import org.glassfish.jersey.server.ResourceConfig;

public class ApplicationConfig  extends ResourceConfig {
    public ApplicationConfig() {
        register(new ApplicationBinder());
        packages(true, "api");
    }
}

AbstractBinder

抽象活页夹

public class ApplicationBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(PricingService.class).to(PricingService.class).in(Singleton.class);
    }
}

PricingResource

定价资源

@Path("/prices")
public class PricingResource {
    private final PricingService pricingService;

    @Inject
    public PricingResource(PricingService pricingService) {
        this.pricingService = pricingService;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Collection<Price> findPrices() {
        return pricingService.findPrices();
    }
}

PricingService

定价服务

@Singleton
public class PricingService {
   // no constructors...
// findPrices() ...

}


UPDATE

更新

public class Main {
    public static final String BASE_URI = "http://localhost:8080/api/";

    public static HttpServer startServer() {
        return createHttpServerWith(new ResourceConfig().packages("api").register(HymansonFeature.class));
    }

    private static HttpServer createHttpServerWith(ResourceConfig rc) {
        HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
        StaticHttpHandler staticHttpHandler = new StaticHttpHandler("src/main/webapp");
        staticHttpHandler.setFileCacheEnabled(false);
        staticHttpHandler.start();
        httpServer.getServerConfiguration().addHttpHandler(staticHttpHandler);
        return httpServer;
    }

    public static void main(String[] args) throws IOException {
        System.setProperty("java.util.logging.config.file", "src/main/resources/logging.properties");
        final HttpServer server = startServer();

        System.out.println(String.format("Jersey app started with WADL available at "
                + "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
        server.start();
        System.in.read();
        server.stop();
    }

}

UPDATE3:

更新3:

public class PricingResourceTest extends JerseyTest {
    @Mock
    private PricingService pricingServiceMock;

    @Override
    protected Application configure() {
        MockitoAnnotations.initMocks(this);
        enable(TestProperties.LOG_TRAFFIC);
        enable(TestProperties.DUMP_ENTITY);

        ResourceConfig config = new ResourceConfig(PricingResource.class);
        config.register(new AbstractBinder() {
            @Override
            protected void configure() {
                bind(pricingServiceMock).to(PricingService.class);
            }
        });
        return config;
    }

    @Test
    public void testFindPrices(){
        when(pricingServiceMock.findPrices()).thenReturn(getMockedPrices());
        Response response  = target("/prices")
                .request()
                .get();
        verify(pricingServiceMock).findPrices();
        List<Price> prices = response.readEntity(new GenericType<List<Price>>(){});
//        assertEquals("Should return status 200", 200, response.getStatus());
        assertTrue(prices.get(0).getId() == getMockedPrices().get(0).getId());
    }

    private List<Price> getMockedPrices(){
        List<Price> mockedPrices = Arrays.asList(new Price(1L, 12.0, 50.12, 12L));
        return mockedPrices;
    }
}

JUnit output:

JUnit 输出:

INFO: 1 * Client response received on thread main
1 < 200
1 < Content-Length: 4
1 < Content-Type: application/json
[{}]


java.lang.AssertionError

While debugging:

调试时:

prices.get(0)is Priceobject that has nullassigned to all fields.

prices.get(0)是分配给所有字段的Price对象null



UPDATE4:

更新4:

Added to configure():

添加到configure()

 config.register(HymansonFeature.class);
 config.register(HymansonJsonProvider.class);

Now Junit output a bit better:

现在 Junit 输出好一点了:

INFO: 1 * Client response received on thread main
1 < 200
1 < Content-Length: 149
1 < Content-Type: application/json
[{"id":2,"recurringPrice":122.0,"oneTimePrice":6550.12,"recurringCount":2},{"id":2,"recurringPrice":122.0,"oneTimePrice":6550.12,"recurringCount":2}]

Indeed list priceshas correct number of pricesbut all prices' fields is null. That leads to assumption that problem might be reading entity:

确实列表prices具有正确的数量,prices但所有价格的字段都为null。这导致假设问题可能是读取实体:

List<Price> prices = response.readEntity(new GenericType<List<Price>>(){});

Here is how to fix it

这是修复方法

Change Moxy dependency to:

将 Moxy 依赖更改为:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-Hymanson</artifactId>
</dependency>

and add annotations on 'Price' object.

并在“价格”对象上添加注释。

@XmlRootElement
@JsonIgnoreProperties(ignoreUnknown = true)

采纳答案by Paul Samsotha

Forget the InjectableProvider. You don't need it. The problem is that the mockservice is not the one being injected. It is the one created by the DI framework. So you are checking for changes on the mock service, which has never been touched.

忘记了InjectableProvider。你不需要它。问题是模拟服务不是被注入的服务。它是由 DI 框架创建的。因此,您正在检查从未接触过的模拟服务上的更改。

So what you need to do is bind the mock with the DI framework. You can simply create another AbstractBinderfor testing. It can be a simple anonymous one, where you will bind the mock

所以你需要做的是将模拟与 DI 框架绑定。您可以简单地创建另一个AbstractBinder用于测试。它可以是一个简单的匿名的,您将在其中绑定模拟

ResourceConfig config = new ResourceConfig(PricingResource.class);
config.register(new AbstractBinder() {
    @Override
    protected void configure() {
        bind(pricingServiceMock).to(PricingService.class);
    }
});

Here you are simply binding the mocked service. So the framework will inject the mock into the resource. Now when you modify it in the request, the changes will be seen in the assertion

在这里,您只是绑定了模拟服务。所以框架会将模拟注入资源。现在,当您在请求中修改它时,将在断言中看到更改

Oh and you still need to do your when(..).then(..)to initialize the data in the mock service. That is also what you are missing

哦,您仍然需要when(..).then(..)在模拟服务中初始化数据。这也是你所缺少的

@Test
public void testFindPrices(){
    Mockito.when(pricingServiceMock.findSomething()).thenReturn(list);

回答by nrkkalyan

I fixed this problem by adding the following dependency to my application. compile group: 'org.glassfish.jersey.containers.glassfish', name: 'jersey-gf-cdi', version: '2.14'

我通过向我的应用程序添加以下依赖项来解决这个问题。编译组:'org.glassfish.jersey.containers.glassfish',名称:'jersey-gf-cdi',版本:'2.14'

Then there is no need to have any "AbstractBinder" related code.

那么就不需要有任何“AbstractBinder”相关的代码。

回答by luca.vercelli

The same error arise if beans.xml is missing or placed in the wrong place. This helped me: Where should beans.xml be placed?

如果 beans.xml 丢失或放置在错误的位置,则会出现相同的错误。这对我有帮助:beans.xml 应该放在哪里?