При переносе веб-приложения EJB 2.0 на EJB 3.x забывается значение более низкого уровня

В настоящее время я пытаюсь перенести проект EAR
-Старый проект-
EJB 2.0
Jboss 5.0.1

-Новый проект-
EJB 3.0
Wildfly 13.0.0Final

Его сеансовые компоненты, которые мне удалось создать, и я могу вызвать их. сама по себе логика работает. Проблема, с которой я сталкиваюсь, связана с тем, что одна из последующих операций, кажется, забывает, что она делала.
Текущая проблема, которую я вижу, заключается в следующем:
В веб-приложении в классе мы создаем объект другого класса, который мы затем запускаем его родительский метод. этот родительский метод затем вызывает класс с самим собой в качестве аргумента, который затем проверяет, какой это тип, а затем запускает сеансовый компонент в зависимости от того, какой тип. который затем вызывает функцию аргументов performExecute() в этой функции, мы вызываем запрос и фактически получаем правильные результаты, затем мы добавляем значения наборов результатов в частный член dto. а затем выполняется PerformExecute. и мы возвращаемся к классу веб-приложений, а затем пытаемся получить доступ к тому же члену dto с помощью функции get. это возвращает нулевой указатель. Мне интересно, не забыл ли я что-то в своих сеансовых компонентах?

Старый сеансовый компонент:

public class TxNotSupportedCommandServerBean implements SessionBean {
 SessionContext sessionContext;

 public void ejbCreate() throws CreateException {}

 public void ejbRemove() {
   sessionContext = null;
 }

 public void ejbActivate() {}

 public void ejbPassivate() {}

 public void setSessionContext(SessionContext sessionContext) {
  this.sessionContext = sessionContext;
 }

 public void executeCommand(TargetableCommand cmd) throws CommandException {
  try {
   cmd.performExecute();
  }
  catch (CommandException ex) {
   throw ex;
  }
 }
}

Новый:

@Stateless
@Remote
@TransactionManagement(value=TransactionManagementType.CONTAINER)
@TransactionAttribute(value=REQUIRED)
public class TxNotSupportedCmdServerBean  implements TxNotSupportedCmdServerRemote{

    /**
     * Default constructor. 
     */
    public TxNotSupportedCmdServerBean() {
        // TODO Auto-generated constructor stub
    }
    
    public void executeCommand(TargetableCommand cmd) throws CommandException {
        try {
          cmd.performExecute();
        }
        catch (CommandException ex) {
          throw ex;
        }
      }

}

Оба они находятся в EJB.Jar
интерфейс реализован в EJBClient.jar
Старый интерфейс:

public interface TxNotSupportedCommandServerLocal extends EJBLocalObject {
  public void executeCommand(TargetableCommand cmd) throws CommandException;
}

Новый интерфейс:

public interface TxNotSupportedCmdServerRemote {
    public void executeCommand(TargetableCommand cmd) throws CommandException;
}

А вот и следующий набор файлов, который также находится в EJBClient.jar
TargetableCommand:

public abstract class TargetableCommand implements Command {
  private boolean constraintViolated;      
  protected RequestContext requestContext; 
  protected String dataSourceName;         


  public TargetableCommand(RequestContext requestContext, String dataSourceName) {
    this.requestContext = requestContext;
    this.dataSourceName = dataSourceName;
  }

  public TargetableCommand(RequestContext requestContext) {
    this.requestContext = requestContext;
  }

  public TargetableCommand(String dataSourceName) {
    this.dataSourceName = dataSourceName;
  }

  public TargetableCommand() {
  }

  public void setConstraintViolated(boolean constraintViolated) {
    this.constraintViolated = constraintViolated;
  }

  public boolean isConstraintViolated() {
    return constraintViolated;
  }

  public abstract void performExecute() throws CommandException;

  public void execute() throws CommandException {
    CommandTarget.executeCommand(this);
  }
}

Команда:

public interface Command extends Serializable {
  public void execute() throws CommandException;
}

Закомментированный код — это старые сеансовые компоненты.
CommandTarget:

public class CommandTarget {
  public CommandTarget() {
  }

  /**
   * Exekverar ett kommando i rätt miljö, t.ex. med eller utan transaktionshantering
   * @param cmd TargetableCommand Kommandot som ska utföras
   * @throws CommandException
   */
  public static void executeCommand(TargetableCommand cmd) throws CommandException {
      Context context = null;
      try {
      ServiceLocator sl = ServiceLocator.getInstance();

//      if (cmd instanceof TxRequired) {
//        TxRequiredCommandServerLocalHome cmdSrvHome = (TxRequiredCommandServerLocalHome) sl.getEJBLocalHome("TxRequiredCommandServer");
//        TxRequiredCommandServerLocal cmdSrv = cmdSrvHome.create();
//        cmdSrv.executeCommand(cmd);
//      }
//      else if(cmd instanceof TxNotSupported) {
//        TxNotSupportedCommandServerLocalHome cmdSrvHome = (TxNotSupportedCommandServerLocalHome) sl.getEJBLocalHome("TxNotSupportedCommandServer");
//        TxNotSupportedCommandServerLocal cmdSrv = cmdSrvHome.create();
//        cmdSrv.executeCommand(cmd);
//      }
//      else {
//        throw new CommandException("Cannot instanciate command server");
//      }
//      
      System.out.println("CT: Inside commandTarget. about to diffrientate what instance");
      context = JNDILookupClass.getInitialContext();
      if (cmd instanceof TxRequired) {
                System.out.println("CT: TxRequired");
              TxRequiredCmdServerRemote cmdSrv = (TxRequiredCmdServerRemote)context.lookup(JNDILookupClass.getLookupName("TxRequiredCmdServerRemoteBean", TxRequiredCmdServerRemote.class.getName()));
              cmdSrv.executeCommand(cmd);
        }
        else if(cmd instanceof TxNotSupported) {
            System.out.println("CT: TxNotSupported");
            System.out.println("CT: cmd: " + cmd.getClass());
            TxNotSupportedCmdServerRemote cmdSrv = (TxNotSupportedCmdServerRemote)context.lookup(JNDILookupClass.getLookupName("TxNotSupportedCmdServerBean", TxNotSupportedCmdServerRemote.class.getName()));
            cmdSrv.executeCommand(cmd);
        }
        else {
          throw new CommandException("Cannot instanciate command server");
        }
    }
    catch (CommandException ex) {
      throw ex;
    }
//    catch (CreateException ex) {
//      throw new CommandException(ex);
//    }
      //new catch
    catch(NamingException ex) {
     throw new CommandException(ex);
    }
    catch (ServiceLocatorException ex) {
      throw new CommandException(ex);
    }
  }
}

Уф... Хорошо, теперь это важные части EJBClient. теперь перейдем к Web.war
Я вставляю только ту часть, которая действительно работает и возвращает нулевую точку

public class ActionIdentitetKonsultCommand implements Command {
    
  private static Logger logger = Logger.getLogger(ActionIdentitetKonsultCommand.class);
  
  public ActionIdentitetKonsultCommand() {
  }

  public String execute(RequestContext requestContext) throws CommandException {
    GetPersonByPersnrEJBCommand personCmd;
    logger.info("execute()");
    try {
      UserBean user = (UserBean) requestContext.getSession().getAttribute("user");
      String kstnr = requestContext.getParameter("kstnr");

      //Tilldela konsultuppgifter
      personCmd = new GetPersonByPersnrEJBCommand();
      personCmd.setPersnr(user.getPersnr());
      System.out.println("AI: Before execute DTO " + personCmd.dto);
      personCmd.execute();
      System.out.println("AI: After execute DTO " + personCmd.dto);
      logger.info("person hamtad med personnummer (EJB):");
      logger.info(personCmd.getPerson().toString()); 

Таким образом, personCmd.getPerson().tostring() вызывает нулевой указатель. GetPersonByPersnrEJBCommand():

public class GetPersonByPersnrEJBCommand extends TargetableCommand implements TxNotSupported {
  public PersonDTO dto;
  private long persnr;

  public GetPersonByPersnrEJBCommand() {
  }

  public void setPersnr(long persnr) {
    this.persnr = persnr;
  }

  public PersonDTO getPerson() {
    return this.dto;
  }

  public void performExecute() throws CommandException {
    try {
      QueryPersonByPersnrCommand cmd = new QueryPersonByPersnrCommand();
     
      cmd.setPersnr(persnr);
      cmd.execute();

      if(cmd.next()){
        this.dto = new PersonDTO();
        System.out.println("GP: inside PerformExecute DTO: " + dto);
        dto.setPersnr(cmd.getPersnr());
        dto.setEfternamn(cmd.getEfternamn());
        dto.setFornamn(cmd.getFornamn());
        dto.setEpostAdress(cmd.getEpostAdress());
        dto.setKonsult((cmd.getKonsult() == 1));
        dto.setAnsvarig((cmd.getAnsvarig() == 1));
        
        System.out.println("GP: Inside Perform Execute DTO: " + dto);
      }
    }
    catch (DataAccessCommandException ex) {
        System.out.println("GetPersonByPersnrEJBCommand.performExecute misslyckades " + ex.getMessage());
      throw new CommandException(ex);
    }
  }
}

Итак, это все; Я не понимаю, почему он забывает это. когда мы делаем sysouts внутри последнего класса, мы видим, что и в dto, и в cmd есть данные, но как только функция завершается, и мы возвращаемся в класс, который вызывал это, данные пусты. Я подозреваю, что это как-то связано с моими сеансовыми компонентами, мне не хватает свойства или чего-то еще. потому что этот код работает со старыми компонентами на старом сервере JBOSS. Надеюсь, кто-то может помочь мне, и другие могут извлечь из этого уроки, а также я.


person VeryTired    schedule 12.10.2018    source источник
comment
Поможет ли изменение TxNotSupportedCmdServerBean на Stateful или Service/Singleton? Как насчет удаления атрибутов, связанных с транзакцией?   -  person JGlass    schedule 12.10.2018
comment
В первой версии моего bean-компонента у меня не было атрибутов, связанных с транзакцией, и все равно я получил тот же результат. Я еще не пробовал Stateful или сервис/синглтон. Я попробую это в понедельник, когда снова доберусь до кода. Большое спасибо за советы. Я отчитаюсь, к чему это привело.   -  person VeryTired    schedule 12.10.2018
comment
Я попытался изменить его на состояние с сохранением состояния, а также удалил атрибуты транзакции. Это не дало никаких других результатов. Тем не менее, он забывает данные, как только возвращается к ActionIdentitetKonsult. Я еще не разобрался с сервисом/синглтоном, в основном из-за того, что я не совсем уверен, что мне делать.   -  person VeryTired    schedule 16.10.2018
comment
Я немного в тупике, поэтому вы можете попробовать поспрашивать на форумах JBoss Dev. Если вы разобрались, ответьте на свой вопрос, чтобы помочь другим! Удачи!   -  person JGlass    schedule 16.10.2018
comment
Спасибо :) Буду офц. Мне удалось создать небольшой проект, который на самом деле имеет ту же проблему без чувственных данных и без необходимости подключения дБ. Спасибо за совет и помощь оф.   -  person VeryTired    schedule 17.10.2018


Ответы (1)


Мне удалось решить эту проблему. Поскольку масштаб проекта заключается в том, чтобы заставить это работать. Это не красивое решение, и с большим количеством времени переписывания это было бы лучше. Итак, переходим к решению: нам нужно изменить как bean-компонент, targetableCommand, CommandTarget, так и GetPersonByPersnrEJBCommand

TargetableCommand — добавить метод:

public TargetableCommand execute(TargetableCommand  cmd) throws CommandException
{    
    return CommandTarget.executeCommand(cmd);
}

CommandTarget — мы меняем метод executeCommand, чтобы он возвращал TargetableCommand, и убеждаемся, что после завершения работы bean-компонента мы возвращаем этот cmd.

public static TargetableCommand executeCommand(TargetableCommand cmd) throws CommandException {
  Context context = null;
  try {     
  context = JNDILookupClass.getInitialContext();
  if (cmd instanceof TxRequired) {
          TxRequiredCmdServerRemote cmdSrv = (TxRequiredCmdServerRemote)context.lookup(JNDILookupClass.getLookupName("TxRequiredCmdServerRemoteBean", TxRequiredCmdServerRemote.class.getName()));
         cmd = cmdSrv.executeCommand(cmd);
    }
    else if(cmd instanceof TxNotSupported) {
        TxNotSupportedCmdServerRemote cmdSrv = (TxNotSupportedCmdServerRemote)context.lookup(JNDILookupClass.getLookupName("TxNotSupportedCmdServerBean", TxNotSupportedCmdServerRemote.class.getName()));
       cmd = cmdSrv.executeCommand(cmd);
    }
    else {
      throw new CommandException("Cannot instanciate command server");
    }
}
catch (CommandException ex) {
  throw ex;
}
catch(NamingException ex) {
 throw new CommandException(ex);
}
}
return cmd;
}

Бин - измените команду Execute метода, чтобы она возвращала Targetablecommand

public TargetableCommand executeCommand(TargetableCommand cmd) throws CommandException {
    try {
      cmd = cmd.performExecute();
    }
    catch (CommandException ex) {
      throw ex;
    }
return cmd;
  }

Затем, наконец, чтобы заставить все это работать, мне пришлось создать новый метод в классах, которые должны были выполнять выполнение, поэтому в классе GetPersonByPersnrEJBCommand я создал метод wf13Layer(); это просто дополнительный шаг:

public void wf13Layer() throws CommandException
{
    GetPersonByPersnrEJBCommand tmp;
    try{
       tmp = (GetPersonByPersnrEJBCommand) execute(this);
       dto = tmp.getPerson();
    } catch (Exception ex) {
      throw new CommandException(ex);
    }
}

Это то, что я сделал, чтобы заставить его работать. как я уже сказал, это не красивое решение, но оно работает. IT кажется комбинацией, когда мы пересекаемся между проектами, масштаб исчезает. и чтобы получить его дальше, нам нужно наслоить его вот так. Я действительно надеюсь, что это поможет кому-то в какой-то момент, так как там много старого кода.

С уважением

person VeryTired    schedule 06.11.2018