Jpos Q2 服务器与 Spring Boot 2.3

huangapple go评论70阅读模式
英文:

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 -->

&lt;server class=&quot;org.jpos.q2.iso.QServer&quot; logger=&quot;Q2&quot; name=&quot;DownloadServer-A&quot;&gt;
&lt;attr name=&quot;port&quot; type=&quot;java.lang.Integer&quot;&gt;6400&lt;/attr&gt;
&lt;attr name=&quot;minSessions&quot; type=&quot;java.lang.Integer&quot;&gt;10&lt;/attr&gt;
&lt;attr name=&quot;maxSessions&quot; type=&quot;java.lang.Integer&quot;&gt;1100&lt;/attr&gt;
&lt;channel name=&quot;DownloadServer-A-Channel&quot; class=&quot;org.jpos.iso.channel.NACChannel&quot; logger=&quot;Q2&quot;
packager=&quot;org.jpos.iso.packager.GenericPackager&quot; header=&quot;6000010000&quot;&gt;
&lt;property name=&quot;packager-config&quot; value=&quot;/app/repository/q2serverconfig/resources/Download_generic.xml&quot; /&gt;
&lt;/channel&gt;
&lt;request-listener class=&quot;DownloadServerAListener&quot; logger=&quot;Q2&quot;&gt;
&lt;property name=&quot;space&quot; value=&quot;transient:default&quot; /&gt;
&lt;property name=&quot;queue&quot; value=&quot;TransactionQueue&quot; /&gt;
&lt;property name=&quot;timeout&quot; value=&quot;35000&quot; /&gt;
&lt;/request-listener&gt;
&lt;/server&gt;

<!-- 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(&lt;deploydir&gt;);
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

huangapple
  • 本文由 发表于 2020年9月12日 18:35:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/63859419.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定