Jpos Q2 Server with Spring boot 2.3

2.4k views Asked by At

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.

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

There are 1 answers

0
Supun Athukorala On BEST ANSWER

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