I am attempting to create 10_channel.xml and 20_mux.xml Beans dynamically, while Q2 is running already.
The user will provide info via JSON post request like below:
"config": {
"keyset": "KEYSET_1",
"pinblockFmt": "01 - ISO 0 Format",
"acq": {
"format": "VISANET",
"portNumber": 9405
},
"iss": {
"format": "ISO4",
"portNumber": 9488
}
}
The code will take the above info, and use JDOM2 to create the xml files and place them in Q2 deploy folder
private void createJposChannel(Map<String, Object> client, String portName) {
String isoChannel;
String ip;
if (client.get("format").toString().equalsIgnoreCase("VISANET")) {
isoChannel = "org.jpos.iso.channel.VAPChannel";
} else {
isoChannel = "org.jpos.iso.channel.CSChannel";
}
if (client.containsKey("ip")) {
ip = (String) client.get("ip");
} else {
ip = "10.x.x.x";
}
try {
Element channelAdaptor = new Element("channel-adaptor");
channelAdaptor.setAttribute("name", portName + "-channel");
channelAdaptor.setAttribute("class", "org.jpos.q2.iso.ChannelAdaptor");
channelAdaptor.setAttribute("logger", "Q2");
Element channel = new Element("channel");
channel.setAttribute("class", isoChannel);
channel.setAttribute("packager", "org.jpos.iso.packager.GenericPackager");
channel.setAttribute("logger", "Q2");
Element property0 = new Element("property");
property0.setAttribute("name", "packager-config");
property0.setAttribute("value", "src/main/resources/" +
client.get("format").toString().toLowerCase() + ".xml");
Element property1 = new Element("property");
property1.setAttribute("name", "host");
property1.setAttribute("value", ip);
Element property2 = new Element("property");
property2.setAttribute("name", "port");
property2.setAttribute("value", portName.split("-")[0]); //remove system #
Element property3 = new Element("property");
property3.setAttribute("name", "timeout");
property3.setAttribute("value", "3600000"); //default timeout time
channel.addContent(property0);
channel.addContent(property1);
channel.addContent(property2);
channel.addContent(property3);
Element in = new Element("in");
in.setText(portName + "-channel-send");
Element out = new Element("out");
out.setText(portName + "-channel-receive");
Element reconnect = new Element("reconnect-delay");
reconnect.setText("10000");
channelAdaptor.addContent(channel);
channelAdaptor.addContent(in);
channelAdaptor.addContent(out);
channelAdaptor.addContent(reconnect);
IsotesttoolApplication.q2.deployElement(channelAdaptor, String.format("10_%s_channel.xml", portName), false, true);
Thread.sleep(2000);
/*XMLOutputter xmlOutput = new XMLOutputter();
xmlOutput.setFormat(Format.getPrettyFormat());
xmlOutput.output(channelAdaptor, System.out);*/
} catch (IOException e) {
e.printStackTrace();
} catch (ISOException e) {
throw new RuntimeException(e);
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
There is very similar code creating the mux files as well. Will omit to keep post shorter.
However, I am getting the below error only for the acq channel, 10_9405-01_channel.xml. The muxes, and even the channel for port 9488, do not get any errors:
<log realm="Q2.system" at="2023-10-20T12:09:52.198">
<info>
created deploy/10_9405-01_channel.xml
</info>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:52.203">
<warn>
Error Tidying. Could not tidy C:\Users\username\ISOTOPE\src\main\java\deploy\10_9405-01_channel.xml out of the way, by adding .BAD
It could not be called: C:\Users\username\ISOTOPE\src\main\java\deploy\10_9405-01_channel.xml.BAD see log above for detail of problem.
</warn>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:52.203" lifespan="3ms">
<info>
<exception name="Error on line 1 of document file:/C:/Users/username/ISOTOPE/src/main/java/deploy/10_9405-01_channel.xml: Premature end of file.">
org.jdom2.input.JDOMParseException: Error on line 1 of document file:/C:/Users/username/ISOTOPE/src/main/java/deploy/10_9405-01_channel.xml: Premature end of file.
at org.jdom2.input.sax.SAXBuilderEngine.build(SAXBuilderEngine.java:230)
at org.jdom2.input.sax.SAXBuilderEngine.build(SAXBuilderEngine.java:277)
at org.jdom2.input.sax.SAXBuilderEngine.build(SAXBuilderEngine.java:264)
at org.jdom2.input.SAXBuilder.build(SAXBuilder.java:1104)
at org.jpos.q2.Q2.deploy(Q2.java:563)
at org.jpos.q2.Q2.deploy(Q2.java:392)
at org.jpos.q2.Q2.run(Q2.java:258)
at java.lang.Thread.run(Thread.java:750)
Caused by: org.xml.sax.SAXParseException; systemId: file:/C:/Users/username/ISOTOPE/src/main/java/deploy/10_9405-01_channel.xml; lineNumber: 1; columnNumber: 1; Premature end of file.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:178)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1467)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1042)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:113)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:507)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:867)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:796)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:142)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1216)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:644)
at org.jdom2.input.sax.SAXBuilderEngine.build(SAXBuilderEngine.java:217)
... 7 more
</exception>
</info>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:52.204">
<info>
modified deploy/10_9405-01_channel.xml
</info>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:52.211" lifespan="6ms">
<info>
deploy: C:\Users\username\ISOTOPE\src\main\java\deploy\10_9405-01_channel.xml
</info>
</log>
<log realm="channel/10.x.x.x:9405" at="2023-10-20T12:09:52.328" lifespan="81ms">
<connect>
Try 0 10.x.x.x:9405
Connection established to 10.x.x.x:9405
</connect>
</log>
<channel-adaptor name="9405-01-channel" class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2">
<channel class="org.jpos.iso.channel.VAPChannel" packager="org.jpos.iso.packager.GenericPackager" logger="Q2">
<property name="packager-config" value="src/main/resources/visanet.xml" />
<property name="host" value="10.x.x.x" />
<property name="port" value="9405" />
<property name="timeout" value="3600000" />
</channel>
<in>9405-01-channel-send</in>
<out>9405-01-channel-receive</out>
<reconnect-delay>10000</reconnect-delay>
</channel-adaptor><log realm="Q2.system" at="2023-10-20T12:09:54.220">
<info>
created deploy/20_9405-01_mux.xml
</info>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:54.238" lifespan="16ms">
<info>
deploy: C:\Users\username\ISOTOPE\src\main\java\deploy\20_9405-01_mux.xml
</info>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:54.238">
<info>
modified deploy/20_9405-01_mux.xml
</info>
</log>
<mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="9405-01-mux" realm="9405-01-realm">
<in>9405-01-channel-receive</in>
<out>9405-01-channel-send</out>
<ready>9405-01-channel.ready</ready>
<request-listener class="com.visa.ip.isotesttool.service.EchoResponder" />
<request-listener class="com.visa.ip.isotesttool.service.AutoResponder" />
</mux><log realm="Q2.system" at="2023-10-20T12:09:56.239">
<info>
created deploy/10_9488-01_channel.xml
</info>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:56.242" lifespan="3ms">
<info>
deploy: C:\Users\username\ISOTOPE\src\main\java\deploy\10_9488-01_channel.xml
</info>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:56.257">
<info>
modified deploy/10_9488-01_channel.xml
</info>
</log>
<log realm="channel/10.x.x.x:9488" at="2023-10-20T12:09:56.343" lifespan="86ms">
<connect>
Try 0 10.x.x.x:9488
Connection established to 10.x.x.x:9488
</connect>
</log>
<channel-adaptor name="9488-01-channel" class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2">
<channel class="org.jpos.iso.channel.CSChannel" packager="org.jpos.iso.packager.GenericPackager" logger="Q2">
<property name="packager-config" value="src/main/resources/iso4.xml" />
<property name="host" value="10.x.x.x" />
<property name="port" value="9488" />
<property name="timeout" value="3600000" />
</channel>
<in>9488-01-channel-send</in>
<out>9488-01-channel-receive</out>
<reconnect-delay>10000</reconnect-delay>
</channel-adaptor><log realm="Q2.system" at="2023-10-20T12:09:58.245">
<info>
created deploy/20_9488-01_mux.xml
</info>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:58.251" lifespan="3ms">
<info>
deploy: C:\Users\username\ISOTOPE\src\main\java\deploy\20_9488-01_mux.xml
</info>
</log>
<log realm="Q2.system" at="2023-10-20T12:09:58.252">
<info>
modified deploy/20_9488-01_mux.xml
</info>
</log>
Also, as you can see from the logs, it looks like the 10_9405-01_channel
and mux are both deploying anyways, after the error. My program is able to run fine despite that error, and I can see the transaction flow like I expect to.
So why is it complaining about "Error Tidying" and why is it only for one channel xml, and not the other?
Edit: Here is the generated deploy file that is failing
<?xml version="1.0" encoding="UTF-8"?>
<channel-adaptor name="9405-01-channel" class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2" instance="208ac0a3-2b7e-4282-aab4-301d4f0859c3">
<channel class="org.jpos.iso.channel.VAPChannel" packager="org.jpos.iso.packager.GenericPackager" logger="Q2">
<property name="packager-config" value="src/main/resources/visanet.xml" />
<property name="host" value="10.x.x.x" />
<property name="port" value="9405" />
<property name="timeout" value="3600000" />
</channel>
<in>9405-01-channel-send</in>
<out>9405-01-channel-receive</out>
<reconnect-delay>10000</reconnect-delay>
</channel-adaptor>
versus the same code generated for the issuer port, which is not failing:
<?xml version="1.0" encoding="UTF-8"?>
<channel-adaptor name="9488-01-channel" class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2" instance="208ac0a3-2b7e-4282-aab4-301d4f0859c3">
<channel class="org.jpos.iso.channel.CSChannel" packager="org.jpos.iso.packager.GenericPackager" logger="Q2">
<property name="packager-config" value="src/main/resources/iso4.xml" />
<property name="host" value="10.x.x.x" />
<property name="port" value="9488" />
<property name="timeout" value="3600000" />
</channel>
<in>9488-01-channel-send</in>
<out>9488-01-channel-receive</out>
<reconnect-delay>10000</reconnect-delay>
</channel-adaptor>
Judging for the message:
And the fact that it works for other channels, I would say it's most probably due to
Q2
starting to read the file before it is completely written.You should write the files to another temp folder and then perform a move operation, so that, when Q2 sees the file, it is already completely written.
Even if you didn't have this problem, that is a good practice, because if it doesn't happen frequently, it could happen sometime. That code would be in the
IsotesttoolApplication.q2.deployElement(
method.EDIT: I see the
deployElement
method is from theQ2
class, perhaps that method you do what I said, in that case, you could create an issue in the jPOS's GitHub.Meanwhile, a workaround would be to write your version of the method that writes to another place and then perform the move.
EDIT 2: If the error consistently happens in the same way. It may be because
Q2
starts reading the second file, just after it was created. The error is consistent with having an empty XML file in thedeploy
directory:Will produce this:
Which is the same as yours.
So, I would try to add some time between the calls to
Q2.deploy
. Or, on the contrary, if you are processing them in different places, you could also check if creating the elements first, and then deploy them all at once could also work, but there is no warranty.The best approach would be to try to fix that in jPOS, but for that you should provide a minimal reproducible example and create the issue.