Подтвердить что ты не робот

Как заменить @ManagedBean/@ViewScope на CDI в JSF 2.0/2.1

В настоящее время я оцениваю Java EE 6/JSF 2.1 с помощью RichFaces.

A bean, который объявлен как

@ManagedBean
@ViewScoped
  • Получает набор идентификаторов (для подготовки, например, операции удаления).
  • Через JSF отображается всплывающее окно подтверждения.
  • Если пользователь подтверждает, вызывается метод удаления и удаляет строку, для которой идентификатор был сохранен на шаге 1.

Поскольку CDI beans не имеет ViewScope, я попытался объявить bean как:

@Named
@ConversationScoped

Теперь обработка завершилась с ошибкой на шаге 3., поскольку значение, которое было установлено на шаге 1 (отмечено этим), больше не доступно.

Нужно ли использовать методы Conversation.begin() и Conversation.end()?

Если да, то где было бы хорошим местом для их вызова?

4b9b3361

Ответ 1

Если вы можете перейти на JSF 2.2, немедленно сделайте это. Он предлагает встроенную аннотацию @ViewScoped для CDI.

import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}

В качестве альтернативы установите OmniFaces, который приносит свой собственный CDI-совместимый @ViewScoped, включая рабочий @PreDestroy (который разбит на JSF @ViewScoped).

import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}

Другой альтернативой является установка MyFaces CODI, который прозрачно соединяет JSF 2.0/2.1 @ViewScoped с CDI. Это добавляет только параметр автогенерированного запроса в URL (например, @ConversationScoped).

import javax.faces.bean.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}

Если вам действительно нужно использовать @ConversationScoped, то вам действительно нужно начинать и заканчивать его. Вам нужно @Inject a Conversation и вызвать begin() в @PostConstruct и end() на последнем шаге разговора, обычно метод действия, который перенаправляется на новое представление.

import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;

@Named
@ConversationScoped
public class Bean implements Serializable {

    @Inject
    private Conversation conversation;

    // ...

    @PostConstruct
    public void init() {
        conversation.begin();
    }

    public String submit() {
        // ...

        conversation.end();
        return "some.xhtml?faces-redirect=true";
    }

}

См. также:

Ответ 2

Я думаю, вы можете использовать расширение CDI для создания своей собственной области, чтобы вы могли реализовать контекст и использовать @NormalScope.

  • CDI запускает событие AfterBeanDiscovery после каждого вызова bean
  • Вы можете использовать расширение CDI для @Observes этого события и добавить свою реализацию контекста.
  • В рамках вашей реализации вы можете:
    • Используйте Contextual, чтобы получить bean по имени от FacesContext ViewRoot Map и вернуть его после каждого обратного вызова ajax
    • Используйте CreationalContext, если имя bean с первого шага не найдено, чтобы создать его в FacesContext ViewRoot Map

Для более подробного объяснения я рекомендую эту ссылку: http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/

Ответ 3

Ввести разговор в ваш bean и в @PostConstructor метод начать разговор, если разговор преходящ.

И после удаления записи завершите разговор и перейдите на страницу назначения. При начале разговора. Вот пример

public class BaseWebBean implements Serializable {

private final static Logger logger = LoggerFactory.getLogger(BaseWebBean.class);
@Inject
protected Conversation conversation;

@PostConstruct
protected void initBean(){
}

public void continueOrInitConversation() {
        if (conversation.isTransient()) {
            conversation.begin();
            logger.trace("conversation with id {} has started by {}.", conversation.getId(), getClass().getName());
        }
    }

public void endConversationIfContinuing() {
        if (!conversation.isTransient()) {
            logger.trace("conversation with id {} has ended by {}.", conversation.getId(), getClass().getName());
            conversation.end();
        }
}

}

@ConversationScoped
@Named
public class yourBean extends BaseWebBean implements Serializable {
    @PostConstruct
    public void initBean() {
        super.initBean();
        continueOrInitConversation();
    }

    public String deleteRow(Row row)
    {
        /*delete your row here*/
        endConversationIfContinuing();
        return "yourDestinationPageAfter removal";
    }

}

Ответ 4

Существует проект, который содержит расширения для функций стека Java EE: DeltaSpike. Это консолидация Seam 3, Apache CODI. Помимо других, он включает @ViewScoped в CDI. Это старая статья, и к настоящему времени она достигла версии 1.3.0

Ответ 5

Вы можете использовать:

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class PageController implements Serializable {

    private String value;

    public void setValue(String value) {
    this.value = value;
    }

    public String getValue() {
    return value;
    }

    public void execute() {
    setValue("value");
    }

    @PostConstruct
    public void init() {
    System.out.println("postcontructor");
    }

}