Возможно, вы используете scoped
контекст EJB для удаленного выполнения метода.
Каждый контекст EJB с заданной областью будет создавать новый поток, и простой вызов метода context.close()
не закроет контекст, поэтому вы получаете OutOfMemoryError
Как закрыть контексты EJB-клиента в определенной области?
Ответ тот же, используйте метод close () в контексте клиента EJB. Но реальный вопрос заключается в том, как получить соответствующий контекст EJB-клиента, связанный с контекстом JNDI. Прежде чем мы перейдем к этому, важно понять, как связано пространство имен ejb: JNDI, используемое для поиска EJB, и как связан контекст JNDI (обычно InitialContext, который вы видите в коде клиента). JNDI API, предоставляемый языком Java, позволяет регистрировать «фабрику контекста URL» в структуре JNDI (подробности см. В этом документе http://docs.oracle.com/javase/jndi/tutorial/provider/url/factory.html). Как и в документации, изложенной в документе, фабрика контекста URL может использоваться для разрешения строк URL во время поиска JNDI. Вот что такое префикс ejb: когда вы выполняете удаленный поиск EJB. Строка ejb: URL поддерживается фабрикой контекста URL.
Внутренне, когда происходит поиск для строки URL-адреса ejb:, для этого ejb: lookup создается соответствующий javax.naming.Context. Давайте посмотрим код для лучшего понимания:
// JNDI context "A"
Context jndiCtx = new InitialContext(props);
// Now let's lookup a EJB
MyBean bean = jndiCtx.lookup("ejb:app/module/distinct/bean!interface");
Итак, сначала мы создаем контекст JNDI, а затем используем его для поиска EJB. Поиск в бине с использованием имени ejb: JNDI, хотя и является лишь одним утверждением, включает в себя еще несколько вещей. Когда вы просматриваете эту строку, на самом деле происходит то, что для строки ejb: URL создается отдельный файл javax.naming.Context. Этот новый javax.naming.Context затем используется для поиска остальной части строки в этом имени JNDI.
Давайте разберем эту строку на несколько операторов, чтобы лучше понять:
// Remember, the ejb: is backed by a URL context factory which returns a Context for the ejb: URL (that's why it's called a context factory)
final Context ejbNamingContext = (Context) jndiCtx.lookup("ejb:");
// Use the returned EJB naming context to lookup the rest of the JNDI string for EJB
final MyBean bean = ejbNamingContext.lookup("app/module/distinct/bean!interface");
Как вы видите выше, мы разделили это единственное утверждение на пару утверждений, чтобы лучше объяснить детали. Итак, как вы можете видеть, когда строка ejb: URL анализируется в имени JNDI, она получает экземпляр javax.naming.Context. Этот экземпляр отличается от того, который использовался для поиска (в этом примере jndiCtx). Это важная деталь для понимания (по причинам, объясненным позже). Теперь этот возвращенный экземпляр используется для поиска остальной части строки JNDI («app / module / different / bean! Interface»), которая затем возвращает прокси EJB. Независимо от того, выполняется поиск в одном выражении или в нескольких частях, код работает одинаково. то есть экземпляр javax.naming.Context создается для строки URL ejb: *
Так почему я объясняю все это, когда раздел озаглавлен «Как закрыть контексты EJB-клиента в определенной области»? Причина заключается в том, что клиентские приложения, имеющие дело с контекстами клиента EJB в определенной области, которые связаны с контекстом JNDI, ожидают, что следующий код закроет связанный контекст клиента EJB, но будут удивлены, что это не так:
final Properties props = new Properties();
// mark it for scoped EJB client context
props.put("org.jboss.ejb.client.scoped.context","true");
// add other properties
props.put(....);
...
Context jndiCtx = new InitialContext(props);
try {
final MyBean bean = jndiCtx.lookup("ejb:app/module/distinct/bean!interface");
bean.doSomething();
} finally {
jndiCtx.close();
}
Приложения ожидают, что вызов jndiCtx.close () эффективно закроет клиентский контекст EJB, связанный с контекстом JNDI. Этого не происходит, потому что, как объяснялось ранее, javax.naming.Context, поддерживающий строку URL-адреса ejb:, отличается от экземпляра, который закрывает код. Реализация JNDI в Java только закрывает контекст, в котором было вызвано закрытие. В результате другой javax.naming.Context, который поддерживает строку ejb: URL, все еще не закрыт, что фактически означает, что контекст клиента EJB с заданной областью действия также не закрыт, что в конечном итоге означает, что соединение с сервером (ами) в клиентский контекст EJB тоже не закрыт.
Итак, теперь давайте посмотрим, как это можно сделать правильно. Мы знаем, что поиск строки ejb: URL возвращает нам javax.naming.Context. Все, что нам нужно сделать, это сохранить ссылку на этот экземпляр и закрыть его, когда мы закончим с вызовами EJB. Вот как это будет выглядеть:
final Properties props = new Properties();
// mark it for scoped EJB client context
props.put("org.jboss.ejb.client.scoped.context","true");
// add other properties
props.put(....);
...
Context jndiCtx = new InitialContext(props);
Context ejbRootNamingContext = (Context) jndiCtx.lookup("ejb:");
try {
final MyBean bean = ejbRootNamingContext.lookup("app/module/distinct/bean!interface"); // the rest of the EJB jndi string
bean.doSomething();
} finally {
try {
// close the EJB naming JNDI context
ejbRootNamingContext.close();
} catch (Throwable t) {
// log and ignore
}
try {
// also close our other JNDI context since we are done with it too
jndiCtx.close();
} catch (Throwable t) {
// log and ignore
}
}
Как вы видите, мы изменили код, чтобы сначала выполнить поиск только по строке "ejb:", чтобы получить контекст именования EJB, а затем использовали этот экземпляр ejbRootNamingContext для поиска остальной части имени JJDI EJB, чтобы получить его. прокси EJB. Затем, когда пришло время закрыть контекст, мы закрыли ejbRootNamingContext (а также другой контекст JNDI). Закрытие ejbRootNamingContext гарантирует, что контекст клиента EJB в области действия, связанный с этим контекстом JNDI, также будет закрыт. По сути, это закрывает соединение (я) с сервером (ами) в контексте этого EJB-клиента.
Для более подробной информации вы можете обратиться Контексты клиента EJB Scoped