Джерси @ Контекстная инъекция не работает в классе @Provider [дубликат]

Выполните следующие действия:

  • Создайте новый класс и сделайте его подклассом UITableViewCell и назовите его чем-то вроде MyTableViewCell.
  • В вашем файле раскадровки щелкните свой TableView, затем в правой панели щелкните инспектор атрибутов, выберите ячейки прототипа: 1.
  • Нажмите вновь созданную ячейку и в инспекторе атрибутов выберите имя идентификатора (например, «myCellID»). Затем в инспекторе идентификации установите атрибут класса MyTableViewCell.
  • Перетащите текстовые поля в свою ячейку, затем с помощью помощника редактора, ctrl + click и перетащите его из текстовых полей в подкласс UITableViewCell. Он должен создавать выходы для ваших текстовых полей.
  • В вашем ViewController создайте свой класс для реализации протокола UITableViewDataSource и переопределите tableView(_: numberOfRowsInSection:) и tableview(_: cellForRowAtIndexPath:). Затем в последнем методе напишите: пусть myCell = tableView.dequeueReusableCellWithIdentifier («myCellID») как! MyTableViewCell возвращает myCell

Несмотря на то, что мы не используем выходы для созданных вами текстовых полей, вам нужно будет в какой-то момент использовать их для предварительного заполнения контента, установки методов целевого действия, и др.

92
задан Paul Samsotha 19 February 2016 в 01:51
поделиться

6 ответов

Вам необходимо определить AbstractBinder и зарегистрировать его в приложении JAX-RS. Связывание определяет, как инъекция зависимости должна создавать ваши классы.

public class MyApplicationBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(MyService.class).to(MyService.class);
    }
}

Когда @Inject обнаружен в параметре или поле типа MyService.class, он создается с использованием класса MyService. Чтобы использовать это связующее, его необходимо зарегистрировать в приложении JAX-RS. В web.xml определите приложение JAX-RS следующим образом:

<servlet>
  <servlet-name>MyApplication</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value>com.mypackage.MyApplication</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>MyApplication</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

Внесите класс MyApplication (указанный выше в init-param).

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(new MyApplicationBinder());
        packages(true, "com.mypackage.rest");
    }
}

В конструкторе класса, указанном в конструкторе класса, записывается вставка, определяющая вложение зависимостей, а также приложение, в котором вы можете найти ресурсы REST (в вашем случае MyResource) с помощью вызова метода packages().

92
ответ дан mkobit 19 August 2018 в 14:30
поделиться
  • 1
    Как насчет EntityManager? Любой намек, как связать его, чтобы я мог его внедрить через @PersistenceContext? – Johannes Staehlin 18 June 2013 в 10:15
  • 2
    Я не уверен, что EntityManager, но, судя по docs.oracle.com/javaee/6/api/javax/persistence/… , он кажется интерфейсом. Вы можете связать его с помощью bind(EntityManagerImpl.class).to(EntityManager.class) (который привяжет класс EntityManagerImpl, реализующий интерфейс EntityManager. Если вам нужно использовать фабрику, посмотрите bindFactory() в AbstractBinder. Если вам нужна помощь с это, пожалуйста, создайте новый вопрос (у меня не будет возможности ответить на него в комментариях). Кроме того, я не уверен, что вы должны использовать @PersistentContext, просто используйте @Inject для всего – joscarsson 25 June 2013 в 16:03
  • 3
    Да, EntityManager - это спецификация JPA (Java EE). Спасибо за комментарий, я открою еще один вопрос, если у меня возникнет конкретная проблема! – Johannes Staehlin 25 June 2013 в 16:09
  • 4
    Для записи JPA также работает на Java SE. [Д0] oracle.com/technetwork/java/javaee/tech/… – prefabSOFT 8 September 2013 в 06:51
  • 5
    Что делает привязка? Что делать, если у меня есть интерфейс и реализация? – Dejell 21 January 2014 в 19:06

Oracle рекомендует добавить аннотацию @Path ко всем типам, которые будут вставляться при объединении JAX-RS с CDI: http://docs.oracle.com/javaee/7/tutorial/jaxrs-advanced004.htm Хотя это далеко не идеально (например, вы получите предупреждение от Джерси при запуске), я решил воспользоваться этим путем, что избавит меня от поддержки всех поддерживаемых типов в связующем.

Пример:

@Singleton
@Path("singleton-configuration-service")
public class ConfigurationService {
  .. 
}

@Path("my-path")
class MyProvider {
  @Inject ConfigurationService _configuration;

  @GET
  public Object get() {..}
}
2
ответ дан Benjamin Mesing 19 August 2018 в 14:30
поделиться

Если вы предпочитаете использовать Guice, и вы не хотите объявлять все привязки, вы также можете попробовать этот адаптер:

guice-bridge-jit-injector

0
ответ дан Choi 19 August 2018 в 14:30
поделиться

Поздно, но я надеюсь, что это кому-то поможет.

У меня есть JAX RS, определенный следующим образом:

@Path("/examplepath")
@RequestScoped //this make the diference
public class ExampleResource {

Затем, в моем коде, наконец, я могу ввести:

@Inject
SomeManagedBean bean;

В моем случае SomeManagedBean является компонентом ApplicationScoped.

Надеюсь, это поможет кому угодно.

5
ответ дан gjijon 19 August 2018 в 14:30
поделиться

Сначала просто ответьте на комментарий в ответе accept.

«Что делает привязка? Что делать, если у меня есть интерфейс и реализация?»

Он просто читает bind( implementation ).to( contract ). Вы можете использовать альтернативную цепочку .in( scope ). Область по умолчанию PerLookup. Поэтому, если вам нужен синглтон, вы можете

bind( implementation ).to( contract ).in( Singleton.class );

Также имеется RequestScoped

Кроме того, вместо bind(Class).to(Class) вы также можете bind(Instance).to(Class), который будет быть автоматически одиночным.


Добавление к принятому ответу

Для тех, кто пытается выяснить, как зарегистрировать реализацию AbstractBinder в ваш web.xml (т. е. вы не используете ResourceConfig), похоже, связывание не будет обнаружено через сканирование пакетов, то есть

<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
    <param-value>
        your.packages.to.scan
    </param-value>
</init-param>

Или это либо

<init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
        com.foo.YourBinderImpl
    </param-value>
</init-param>

Чтобы заставить его работать, мне пришлось реализовать Feature :

import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;

@Provider
public class Hk2Feature implements Feature {

    @Override
    public boolean configure(FeatureContext context) {
        context.register(new AppBinder());
        return true;
    }
}

Аннотации @Provider должны позволять выбирать Feature путем сканирования пакета. Или без сканирования пакетов вы можете явно зарегистрировать Feature в web.xml

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>
            com.foo.Hk2Feature
        </param-value>
    </init-param>
    ...
    <load-on-startup>1</load-on-startup>
</servlet>

См. Также:

и для общей информации из документации Джерси


UPDATE

Заводы

от базовой привязки в принятом ответе, у вас также есть заводы, где вы можете иметь более сложную логику создания, а также иметь доступ к информации контекста запроса. Например

public class MyServiceFactory implements Factory<MyService> {
    @Context
    private HttpHeaders headers;

    @Override
    public MyService provide() {
        return new MyService(headers.getHeaderString("X-Header"));
    }

    @Override
    public void dispose(MyService service) { /* noop */ }
}

register(new AbstractBinder() {
    @Override
    public void configure() {
        bindFactory(MyServiceFactory.class).to(MyService.class)
                .in(RequestScoped.class);
    }
});

Затем вы можете ввести MyService в свой класс ресурсов.

44
ответ дан Graham 19 August 2018 в 14:30
поделиться
  • 1
    Я мог бы зарегистрировать свой класс связующего только через реализацию ResourceConfig, как показано в принятом ответе. Нет класса функций. – Patrick Koorevaar 23 September 2016 в 08:54
  • 2
    Используя web.xml, даже если вызывается configure() на Hk2Feature, запрос ресурса выбрасывает NullPointerException. @PaulSamsotha – Shamil 5 June 2018 в 07:03

Выбранный ответ датируется некоторое время назад. Нецелесообразно объявлять каждую привязку в обычном связующем HK2. Я использую Tomcat, и мне просто нужно добавить одну зависимость. Несмотря на то, что он был разработан для Glassfish, он идеально вписывается в другие контейнеры.

   <dependency>
        <groupId>org.glassfish.jersey.containers.glassfish</groupId>
        <artifactId>jersey-gf-cdi</artifactId>
        <version>${jersey.version}</version>
    </dependency>

Убедитесь, что ваш контейнер правильно настроен ( см. документацию ).

11
ответ дан otonglet 19 August 2018 в 14:30
поделиться
  • 1
    Последняя строка (убедитесь, что ваш контейнер также настроен правильно) немного расплывчато. Любая помощь здесь? Какие аннотации мы используем где? – markthegrea 27 June 2016 в 20:42
  • 2
    Мы использовали Weld для инъекции зависимостей, для чего потребовалась специальная конфигурация для работы с Tomcat (наше приложение «контейнер»). Если вы используете Spring, он работает из коробки. – otonglet 26 July 2016 в 09:53
Другие вопросы по тегам:

Похожие вопросы: