0

У меня проблема с использованием entityManager, управляемого EJB Container.Исключение null null указателя EntityManager из Persistence Context Java EE

В моем ухе у меня есть 3 модуля:

-область - Есть классы сущностей и DAO Реализация с интерфейсами как EJBs.

-services - Там у меня была бы логика, связанная с запросами обработки, вызывая исключения бизнес-класса на основе исключений библиотек (например, исключения баз данных).

-Rest Services - Там у меня были бы конечные точки отдыха для приема и отправки некоторых бизнес-объектов.

Таким образом, основная проблема заключается в использовании EJB в слое услуг, я могу объявить класс конечной точки отдыха, класс обслуживания и класс DAO как EJB. Но таким образом я не могу поймать исключения, связанные с базой данных, потому что, поскольку я краснею, я получаю исключение transactionRollback в контейнере EJB, предоставленном WildFly, и это исключение существует при совершении транзакции.

Я думал об удалении аннотации @Stateless из класса сервиса, но когда я это делаю, контейнер EJB не вводит entityManager в мой класс DAO. Также я попытался использовать аннотацию @Inject в классе службы, но все равно получаю то же исключение NullPointer в entityManager в Dao Class.

Ниже я добавляю реализации примеры кода в моем проекте:

DAO Класс:

@Stateless 
public class CardDaoImpl implements CardDao { 

@PersistenceContext(unitName = "test") 
protected EntityManager em; 

public CardBase addCardToDatabase(CardBase card) { 
    em.persist(card); 
    return card; 
} 

Service Class (здесь я хочу обрабатывать businessExceptions):

@Stateless 
public class TestService implements TestServiceIf { 

@EJB(beanInterface = CardDao.class) 
private CardDao dao; 

@Override 
public CardBase addCard(CardBase card) { 
    dao.addCardToDatabase(card); 
    return card; 
} 

} 

Rest Конечная точка класса :

@Stateless 
@Path("/test") 
public class Test { 

@EJB(beanInterface = TestServiceIf.class) 
private TestServiceIf service; 

@GET 
@Path("/test") 
@Produces(MediaType.APPLICATION_JSON) 
public String addCard() { 
    CardBase card = new SampleCard(); 
    //Setting card object fields// 
    service.addCard(card); 
    return "Hello"; 
} 

}

Это только одно решение, которое я обнаружил. Но что с метанием моих businsesExceptions? Может быть, это не хорошая практика бросить их в этот уровень сервиса?

+0

что ваш сервер и ваш EJB версии? К сожалению, по словам сервера, у вас есть особенности даже для спецификации, как EJB. – davidxxx

+0

Я использую Wildfly 10. В модулях этого сервера приложений я нашел EJB3.2 api –

ответ

1

С EJB 3.X у вас есть некоторые особенности об исключениях, возникающих в ejb-методах.

-services - Там я бы логику, связанную с обработкой запросов, вызывая исключения BUSSINESS на основе библиотеки исключений (для например исключений базы данных).

По умолчанию контейнер обручи в техническом (за исключением EJBTransactionRolledbackException) всех исключений, происходящих в EJB, которые он считает неожиданным. Точно так же вы можете поймать все неожиданные исключения в своем приложении. Помимо упаковки исключений, контейнер запускает откат текущей транзакции.
Чтобы избежать обхода технической исключительной ситуации контейнером, ваши бизнес-исключения не должны рассматриваться как непредвиденные контейнером.

В широком смысле, у вас есть два случая:

  • Либо, они проверяются. Нечего делать в этом случае.

  • Либо, это время выполнения. Вы должны добавить аннотацию ApplicationException на них или указать поведение приложения-исключения с помощью xml-конфигурации EJB.

От ApplicationException Javadoc:

: Применительно к исключению, чтобы обозначить, что это исключение применение и должны быть сообщены клиенту непосредственно (то есть развернутом).

Наконец, операция отката может быть желательной или нет. Вы можете настроить его так:

@ApplicationException(rollback=true) 
public class MyBusinessRuntimeException extends RuntimeException { 

или

@ApplicationException(rollback=false) 
public class MyBusinessRuntimeException extends RuntimeException { 

С Weblogic, я помню, я также должен был объявить эти исключения в сигнатуре метода.


Обновление для комментариев:

Но первый мне нужно поймать исключение из Lib третьей стороны, например, ConstraintValueException.

У вас есть два способа сделать. Исправление явно, где проблема может возникнуть или обрабатывать исключение поперечным способом. Я думаю, вы ссылаетесь на ConstraintViolationException.

  • Обработка исключений, где это происходит, когда исключение специфично и требует контекста быть обработано:

Если вы ожидаете конкретное исключение третьей стороны в конкретном случае, вы хотели бы поймайте его, чтобы вернуть свое исключение для бизнеса, вы должны поймать третье исключение, как только оно встанет.
Во-первых, это хорошая практика, чтобы поймать исключение, как только мы знаем, как с ним справиться.
Во-вторых, это исключает возможность исключения исключения на следующий уровень и поэтому превращается в исключение EJBTransactionRolledbackException.
Однако, по-разному, тип исключения может обрабатываться трансверсально по уважительным причинам.
В этом случае вы можете использовать трансверсальную обработку для этого исключения.

  • Поперечная обработка, когда исключение содержит необходимую информацию обращаться:

Если вы хотите обрабатывать ожидаемое исключение во время выполнения в поперечном пути, вы можете использовать перехватчик JEE и ловить его бросать собственное исключение бизнеса.
В этом случае вы должны определить в перехватчике сопоставление между причиной пойманного исключения и настраиваемым исключением.

Пример перехватчик для выполнения вашей потребности (он не обрабатывает все сценарии, только номинальный сценарий):

public class WrappingInBusinessExceptionInterceptor { 

    @AroundInvoke 
    public Object handleExceptions(final InvocationContext ctx) throws Exception { 

     try { 
      Object result = ctx.proceed(); 
      return result; 
     } 

     catch (Exception exception) { 
      // log the root exception 
       ... 
       Exception causeException = e.getCause(); 
       if (causeException !=null && 
        causeException.getClass()==ConstraintValueException.class){ 
        // throw your custom exception 
        String businessMsg = 
         retrieveBusinessMessageFrom(causeException); 
        throw new MyBusinessException(businessMsg); 
       } 
     }        

    } 
+0

Хорошо, это вторая часть решения. Но сначала мне нужно поймать исключение из сторонней библиотеки, например, ConstraintValueException или что-то подобное, когда я добавляю что-то в свою базу данных с существующим значением ключа. Когда я поймаю, что я брошу свое исключение businnesException, чтобы обработать его на интерфейсе с правильным сообщением. –

+0

Я обновил свой ответ. – davidxxx

+0

Хорошо, но вы не видите мою точку зрения. Мой код работает только тогда, когда я отмечаю все классы с аннотацией @Stateless, делая их EJB. Таким образом, контейнер после получения запроса на отдых, вероятно, открывает транзакцию и закрывает ее после того, как данные будут из класса EJB. Например, я тестировал его в сервлете. В классе сервлетов все wroks прекрасны, я мог бы добавить свой объект EJB службы в класс Servlet, который не был EJB, поэтому я мог поймать свое исключение RolledBackTransactionException. –

Смежные вопросы