英文:
Jpos Q2 Server with Spring boot 2.3
问题
我们有一个现有的系统,其中包括Q2服务器和基于Spring MVC的以下配置。当初始化HttpServlet时,Q2服务器被创建并且工作得很好,Spring Bean可以在ISORequestlistner中进行自动装配。现在正在将其转换为Spring Boot 2.3。我使用Spring Boot中的ServletRegistrationBean初始化了相同的HttpServlet,Q2服务器被初始化并且可以向其发送请求。但是自动装配不起作用。经过检查,一旦请求在ISORequest监听器内部进行处理,由于Q2服务器使用了不同的类加载器,Spring上下文就不可见了。
<server class="org.jpos.q2.iso.QServer" logger="Q2" name="DownloadServer-A">
<attr name="port" type="java.lang.Integer">6400</attr>
<attr name="minSessions" type="java.lang.Integer">10</attr>
<attr name="maxSessions" type="java.lang.Integer">1100</attr>
<channel name="DownloadServer-A-Channel" class="org.jpos.iso.channel.NACChannel" logger="Q2"
packager="org.jpos.iso.packager.GenericPackager" header="6000010000">
<property name="packager-config" value="/app/repository/q2serverconfig/resources/Download_generic.xml" />
</channel>
<request-listener class="DownloadServerAListener" logger="Q2">
<property name="space" value="transient:default" />
<property name="queue" value="TransactionQueue" />
<property name="timeout" value="35000" />
</request-listener>
</server>
第一次尝试:
尝试使用ApplicationContextAware创建静态ApplicationContext,并在ISORequest监听器中尝试使用它。但是当TCP请求发送到Q2服务器时,它会变为null。
第二次尝试:
我尝试了一些类似于下面GitHub存储库的解决方案。但是没有成功。
https://github.com/vmantek/chimera
是否有人尝试在Spring应用程序上下文中以bean的形式启动ISO服务器?我的意思是在@Configuration类中使用Q2.start()启动ISO服务器。Q2.start将在单独的类加载器中启动。我不希望这种情况发生。
英文:
We have a existing system with Q2 Server and Spring MVC with following configuration. Q2 server was created when a Httpservlet is initiated and It worked perfectly and spring beans can be autowired withn ISORequestlistner. This is now being converted to Spring boot 2.3. Once I initiated the same Httpservlet using ServletRegistrationBean in Spring boot, Q2 server is initiated and can send requst to it. But auto-wiring is not working. Once I check. Once he request is processing inside the ISORequest listner, Spring context is not visible since Q2 server is using different class loader.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
<server class="org.jpos.q2.iso.QServer" logger="Q2" name="DownloadServer-A">
<attr name="port" type="java.lang.Integer">6400</attr>
<attr name="minSessions" type="java.lang.Integer">10</attr>
<attr name="maxSessions" type="java.lang.Integer">1100</attr>
<channel name="DownloadServer-A-Channel" class="org.jpos.iso.channel.NACChannel" logger="Q2"
packager="org.jpos.iso.packager.GenericPackager" header="6000010000">
<property name="packager-config" value="/app/repository/q2serverconfig/resources/Download_generic.xml" />
</channel>
<request-listener class="DownloadServerAListener" logger="Q2">
<property name="space" value="transient:default" />
<property name="queue" value="TransactionQueue" />
<property name="timeout" value="35000" />
</request-listener>
</server>
<!-- end snippet -->
1st Try
Tried creating static ApplicationContext using ApplicationContextAware and tried it in the ISORequestListner. But It becomes null when TCP request received to Q2 server.
2nd Try
I tried several solutions like below github repo. But I didn't work.
https://github.com/vmantek/chimera
Have anyone tried to start ISO Server inside the Spring Application context as a bean? What I mean is that start ISO Server in @Configuration class with using Q2.start(). Q2.start will start in a separate class loader. I don't want it to happen.
答案1
得分: 0
以下是翻译好的内容:
这几天我一直在寻找解决方法,并尝试了几种方式。问题在于 Spring 是在特定的类加载器中启动的。但是当你像这样启动 Q2 服务器时:
Q2 q2Server = new Q2(<deploydir>);
q2Server.start();
Q2 服务器是在不同的类加载器中启动的。因此 Spring 上下文无法进行自动装配。SpringBeanAutowiringSupport 依赖于 ContextLoader 来检索当前的应用程序上下文,但始终返回 null。
解决方法
你可以注册一个实现 org.springframework.boot.context.embedded.ServletContextInitializer 接口的 Bean,以在 startup() 期间检索应用程序上下文。
@Configuration
public class WebApplicationContextLocator implements ServletContextInitializer {
private static WebApplicationContext webApplicationContext;
public static WebApplicationContext getCurrentWebApplicationContext() {
return webApplicationContext;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
webApplicationContext =
WebApplicationContextUtils.getWebApplicationContext(servletContext);
}
}
然后你可以在 ISORequestListener 类中实现自动装配。
@Component
public class ServiceImpl implements ISORequestListener {
@Autowired
private BackendService backendService;
public ServiceImpl() {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
WebApplicationContext currentContext = WebApplicationContextLocator.getCurrentWebApplicationContext();
bpp.setBeanFactory(currentContext.getAutowireCapableBeanFactory());
bpp.processInjection(this);
}
}
这样自动装配就能正常工作了。我受到了以下回答的启发。
Spring Boot register JAX-WS webservice as bean
英文:
I was looking for these few days and I was trying several ways.
The issue is that Spring is starting in a Specific class loader. But when you start Q2 Server as
Q2 q2Server = new Q2(<deploydir>);
q2Server.start();
Q2 server is starting in a different classloader. Therefore SpringContext was not available for auto wiring. SpringBeanAutowiringSupport depends on ContextLoader to retrieve the current application context, and always get null.
Workaround
You could register a bean that implements org.springframework.boot.context.embedded.ServletContextInitializer to retrieve the application context during startup().
@Configuration
public class WebApplicationContextLocator implements ServletContextInitializer {
private static WebApplicationContext webApplicationContext;
public static WebApplicationContext getCurrentWebApplicationContext() {
return webApplicationContext;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
webApplicationContext =
WebApplicationContextUtils.getWebApplicationContext(servletContext);
}
}
Then you could implement self-autowiring in your ISORequestListener class.
@Component
public class ServiceImpl implements ISORequestListener {
@Autowired
private BackendService backendService;
public ServiceImpl() {
AutowiredAnnotationBeanPostProcessor bpp = new
AutowiredAnnotationBeanPostProcessor();
WebApplicationContext currentContext =
WebApplicationContextLocator.getCurrentWebApplicationContext();
bpp.setBeanFactory(currentContext.getAutowireCapableBeanFactory());
bpp.processInjection(this);
}
}
Then auto wiring working perfectly. I was inspired by following answer.
Spring Boot register JAX-WS webservice as bean
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论