0

I am using jpos 2.1.0 and using JposLogger to generate and rotate iso logs. However i am not able to configure the parameters appropriately due to which neither the logs are rotated based on dates neither i am able to close the open log files.

This is related to the previous issue Too many files open

which i thought was due to issue in using generic packager but while going deeply, it was due to improper closure of files generated by JposLogger, which can be identified using command lsof -p in centos. One file is generated for one request.

[cipsappcen@connectipsappcen local]$ lsof -p 12108 |grep iso.log
java    12108 cipsappcen   36w      REG              253,2     58589 405618549 /u03/connectIPSSRVC/log/iso.log
java    12108 cipsappcen   47w      REG              253,2     58589 405618549 /u03/connectIPSSRVC/log/iso.log

public class Iso8583MessageBOKImpl implements Iso8583Message{
JposLogger logger = new JposLogger(isoLogLocation);
        org.jpos.iso.ISOPackager customPackager = new GenericPackager(isoPackagerLocation+iso8583Properties.getPackager());
        BaseChannel channel = new ASCIIChannel(iso8583Properties.getServerIp(), Integer.parseInt(iso8583Properties.getServerPort()), customPackager);// live
        logger.jposlogconfig(channel);
...
}

public void jposlogconfig(ISOChannel channel){
        try{
            //Configuring Logger   
            Logger logger = new Logger();
            logger.setName("Q2");
            org.jpos.util.DailyLogListener dayLog = new org.jpos.util.DailyLogListener();
            ProtectedLogListener pll = new ProtectedLogListener();
            Configuration protectLogCfg = new SimpleConfiguration();
            protectLogCfg.put("protect", "2");
            pll.setConfiguration(protectLogCfg);
            logger.addListener(pll);

            Configuration dayLogCfg = new SimpleConfiguration();
            dayLogCfg.put("window", "86400");
            dayLogCfg.put("prefix", logLocation);
            dayLogCfg.put("suffix", ".log");  
            dayLogCfg.put("date-format", "-yyyy-MM-dd");
            dayLog.setConfiguration(dayLogCfg);   
            logger.addListener(dayLog);
            logger.addListener(new SimpleLogListener(System.out)); 
            ((LogSource)channel).setLogger(logger, "connectips-channel");

            logger.removeListener(pll);
        }catch(Exception ex){
            System.out.println(ex);
        }
    }

Since files are not closed properly OS is not able to handle the too many open files.

Andrés Alcarraz
  • 1,570
  • 1
  • 12
  • 21
  • Hi, this informations seems to be not enough to help you with your problem, as you say a log file is created for every request, it seems your jposlogconfig methos is being called for every request, so you are creating a new Logger and LogListener in every request, and that's why you have your problem. In order to SimpleLogListener to rotate your log file and all logs go to the same file you need to have only one instance in your whole application. Or else in every instantiation you are telling the listener to create a new file and rotate that newly created file when the window passes – Andrés Alcarraz Jul 03 '19 at 13:18

1 Answers1

1

You need to instantiate your logger and loglisteners only once in your application.

One option is to use Logger.getLogger() to register and create your logger.

First you need to create a logger only once in your application for instance with a method like this

public void initLogger() {
    Logger logger = Logger.getLogger("Q2"); //this creates a logger and register it with Q2 name
    org.jpos.util.DailyLogListener dayLog = new org.jpos.util.DailyLogListener();
    ProtectedLogListener pll = new ProtectedLogListener();
    Configuration protectLogCfg = new SimpleConfiguration();
    protectLogCfg.put("protect", "2");
    pll.setConfiguration(protectLogCfg);
    logger.addListener(pll);

    Configuration dayLogCfg = new SimpleConfiguration();
    dayLogCfg.put("window", "86400");
    dayLogCfg.put("prefix", logLocation);
    dayLogCfg.put("suffix", ".log");  
    dayLogCfg.put("date-format", "-yyyy-MM-dd");
    dayLog.setConfiguration(dayLogCfg);   
    logger.addListener(dayLog);
    logger.addListener(new SimpleLogListener(System.out)); 
    //all set now logger is accessible via Logger.getLogger
}

Then when you create a new channel all you need is to set the previously created logger:

public class Iso8583MessageBOKImpl implements Iso8583Message{
...
        org.jpos.iso.ISOPackager customPackager = new GenericPackager(isoPackagerLocation+iso8583Properties.getPackager());
        BaseChannel channel = new ASCIIChannel(iso8583Properties.getServerIp(), Integer.parseInt(iso8583Properties.getServerPort()), customPackager);// live
        channel.setLogger(Logger.getLogger("Q2"),"connectips-channel");
...
}

Internally Logger.getLogger(String name) creates a new logger if there is no previously registered logger with that name, and registers it in NameRegistrar

Succesive calls with the same name return the previously created one. This way you are creating the files only once.

The most important thing here is that initLogger is only called at the start of your application, for instance (this is not the best way just an example) in a static initializer of your class if that is the only place where you use jpos related class:

public class Iso8583MessageBOKImpl implements Iso8583Message{

    static {
        initLogger();
    }
...

Last but not leas I strongly suggest you to use Q2 for the initialization of jpos objects, this tutorial has all you need to create a channel and a logger.

Then when you want to send a message you don't even need to instantiate the channel, just call QMUX.getMUX(mux-name) and QMUX.request() method to send a message to the channel and receive its response.

Andrés Alcarraz
  • 1,570
  • 1
  • 12
  • 21
  • Thanks a lot, it solved my problem. Regarding using Q2 server i had already tried Q2 as switching server wherein it receives a ISO8583 request and forward it to other CBS/switch with ISO8583 interface. However out here i need to expose customized REST based API which will be called by multiple clients and will be send to multiple banks (ISO8583) based on certain parameters. As i am using Spring boot to handle and process REST based request and converting/forwarding request to banks in a classic manner. Though want to integrating spring and q2 server but have no clue. Kindly help. – Diwas Sapkota Jul 05 '19 at 02:14