<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jPOS.org</title>
	<atom:link href="http://jpos.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://jpos.org/blog</link>
	<description>jPOS rants, propaganda and some useful stuff.</description>
	<lastBuildDate>Wed, 19 Sep 2018 19:44:39 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.0</generator>
	<item>
		<title>jPOS 2.1.2 has been released</title>
		<link>http://jpos.org/blog/2018/09/jpos-2-1-2-has-been-released/</link>
		<pubDate>Wed, 19 Sep 2018 19:43:22 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=978</guid>
		<description><![CDATA[jPOS 2.1.2 has been released, new development version is now 2.1.3-SNAPSHOT Please see the ChangeLog. See Resources Page for details.]]></description>
				<content:encoded><![CDATA[<p>jPOS 2.1.2 has been released, new development version is now 2.1.3-SNAPSHOT</p>
<p>Please see the <a href="http://jpos.org/wiki/ChangeLog">ChangeLog</a>.</p>
<p>See <a href="http://jpos.org/resources">Resources Page</a> for details.</p>
]]></content:encoded>
			</item>
		<item>
		<title>Asking a smart question</title>
		<link>http://jpos.org/blog/2017/11/asking-a-smart-question/</link>
		<pubDate>Fri, 24 Nov 2017 16:19:17 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=954</guid>
		<description><![CDATA[/by apr/ Among the many helpful jPOS developers in our community, @marklsalter stands out for his professional, accurate, and detailed answers, but he has his standards when it comes to how you ask questions. You need to ask a smart question. jPOS has Mark (and Victor, and Andy, and Dave, and Matias, and Chhil, and [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><em>/by apr/</em></p>
<p><em>Among the many helpful jPOS developers in our community, <a href="https://twitter.com/marklsalter">@marklsalter</a> stands out for his professional, accurate, and detailed answers, but he has his standards when it comes to how you ask questions. You need to ask a smart question. jPOS has Mark (and Victor, and Andy, and Dave, and Matias, and Chhil, and Barzi, and, and, and), but if you go to any other open source community asking for free advice, you&#8217;ll find another Mark, or worst than that, you&#8217;ll find no Mark and your question will just get ignored and you won&#8217;t even know why.</em></p>
<p><em>This is what you should expect as a response if you don&#8217;t do your homework and ask a smart question (from a recent reply in jpos-users, in this case, related to a vague question about to the Transaction Manager &#8211; could have been anything else).</em></p>
<hr />
<p>Please always start by asking a smart question.</p>
<p>Please read this now :-</p>
<p><a href="http://www.catb.org/esr/faqs/smart-questions.html">http://www.catb.org/esr/faqs/smart-questions.html</a></p>
<p>Yes, the whole things, go on, treat yourself, it will take 5-10 minutes and save us both hours going forward.</p>
<p>Preparing to ask a smart question should cause you to <em>read</em> the available documentation, to understand it and enable you to make sure you include all the relevant details needed for another remote person to help you, but should also make sure you have understood the documentation and how it applies to your need.</p>
<p>I can honestly say that on this opening post that I could see that it was going to be another thread that would drag on &#8211; without you &#8230;</p>
<ol>
<li>Apparently making any effort to understand what you have done incorrectly or &#8220;misunderstood&#8221;.</li>
<li>Trying first to understand how and why your set-up is broken</li>
<li>Referring to the documentation on the life cycle of the TransactionManager and it&#8217;s given participants &#8211; which perhaps surprisingly, works perfectly when users follow the few simple rules and grasp what it does for you.</li>
</ol>
<p>By the way, I understand that a TM configuration might not be obvious straight away, but often the best things are worth the effort. I still refer to the documentation again and again (and again).</p>
<p>I will include some comment below to, in the hope that you read it and take the time next time to ask a smart question.</p>
<p>Remember as you read through that I am not taking the piss out of you, but trying to highlight why this is a terrible opening question and how you can (hopefully) help yourself next time.</p>
]]></content:encoded>
			</item>
		<item>
		<title>jPOS 2.1.1 has been released</title>
		<link>http://jpos.org/blog/2017/11/jpos-2-1-1-has-been-released/</link>
		<pubDate>Mon, 13 Nov 2017 14:40:12 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=950</guid>
		<description><![CDATA[jPOS 2.1.1 has been released, new development version is now 2.1.2-SNAPSHOT Please see the ChangeLog. See [Resources Page][2] for details.]]></description>
				<content:encoded><![CDATA[<p>jPOS 2.1.1 has been released, new development version is now 2.1.2-SNAPSHOT</p>
<p>Please see the <a href="http://jpos.org/wiki/ChangeLog">ChangeLog</a>.</p>
<p>See [Resources Page][2] for details.</p>
]]></content:encoded>
			</item>
		<item>
		<title>jPOS-EE Crypto Service</title>
		<link>http://jpos.org/blog/2017/10/jpos-ee-crypto-service/</link>
		<pubDate>Fri, 27 Oct 2017 19:18:38 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=936</guid>
		<description><![CDATA[In many jPOS systems, we secure sensitive data using ANS X9.24 DUKPT as described in the Encrypting sensitive data post. The approach served us well, but now we believe we have a better one, using PKI and AES-256. The cryptoservice module uses AES-256 to encrypt sensitive data, such as primary account numbers and protects the [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>In many jPOS systems, we secure sensitive data using ANS X9.24 DUKPT as described in the <a href="http://jpos.org/blog/2006/03/encrypting-sensitive-data/">Encrypting sensitive data</a> post. The approach served us well, but now we believe we have a better one, using PKI and AES-256.</p>
<p>The <code>cryptoservice</code> module uses AES-256 to encrypt sensitive data, such as primary account numbers and protects the encryption key using PGP.</p>
<p>At start-up time, and at regular intervals, the crypto service generates a new AES-256 key, encrypts it using PGP using one or more recipient ids, and stores the resulting encrypted message in the sysconfig table, using the &#8220;key.&#8221; prefix, and a unique key UUID, i.e.:</p>
<pre><code>id: key.f55fe6ec-ed9e-47a1-a0fe-c63dcbf128cb
value:
-----BEGIN PGP MESSAGE-----
Version: BCPG v1.56

hQEMA6Nw6GrTY6BpAQgAs1pUIK3n2FkMyNmfxSZgpPMNFKz39TcfExiwDRtuw+Zg
wRgFw86SJiL1BB+IE+mPAeCz4hrUkzliiu/760NiXHQysIasWEvUZZqFRA+ecNrk
zARgB8vgGTNgxPHoYPafVD5TrxY9LdRpJcO//Wm2fEVw0xc4Q7vxbH7e9gDQfiuA
gcNYk96rVCdbZFKxyMC8fpM9ng6M4V9lxp5TXihzJQEKHWavctIrU2rBolE1WCY2
Oobs1hELW4rfMpVwfGQDtxcFSNDYkd9IO/WnFTtTAxGHs0u1/miRVxNHadLINdke
wXx6au9vq12tqlYaJY+BAEtJaAInwwT5/irHj5dlwtJ0AW2wO3Mwh+A+pGJvSd2T
xyep1pNtm7tMbisZyms0TiGz+6BX6F5ZKCG5UuvsIvTHd/VLp2uajE5NVPe92Y1F
lLbbMyUfxzBwNhwhdfOEWwRAmrt7AbMyAQHUCZAXgwXn7SXsdh8TTzLMsssViD9+
h7lfP9w=
=YyZk

-----END PGP MESSAGE-----
</code></pre>
<p>The key is used to encrypt subsequent data for a given period of time (defaults to one day) until a new key is automatically generated.</p>
<p>Here is a sample usage:</p>
<pre><code>private void encryptCardData (TLCapture tl, Card card)      &lt;1&gt;
   throws Exception {
     Map&lt;String,String&gt; m = new HashMap&lt;&gt;();
     m.put ("P", card.getPan());
     m.put ("E", card.getExp());
     SecureData sd = getCryptoService().aesEncrypt(         &lt;2&gt;
        Serializer.serializeStringMap(m)
     );
     tl.setKid(sd.getId());                                 &lt;3&gt;
     tl.setSecureData(sd.getEncoded());                     &lt;4&gt;
 }
</code></pre>
<ul>
<li>&lt;1> TLCapture in this example is a general purpose capture table.</li>
<li>&lt;2> <code>getCryptoService()</code> just locates the <code>CryptoService</code> using the <code>NameRegistrar</code></li>
<li>&lt;3> <code>kid</code> stands for Key ID, we store the key UUID here</li>
<li>&lt;4> <code>secureData</code> is a general purpose blob</li>
</ul>
<p>The crypto service can be configured using a QBean descriptor like this:</p>
<pre><code>&lt;crypto-service class='org.jpos.crypto.CryptoService' logger='Q2'&gt;
    &lt;property name="custodian" value='demo@jpos.org' /&gt;               &lt;1&gt;
    &lt;property name="pubkeyring" value='cfg/keyring.pub' /&gt;            &lt;2&gt;
    &lt;property name="privkeyring" value='cfg/keyring.priv' /&gt;          &lt;3&gt;
    &lt;property name="lazy" value="false" /&gt;                            &lt;4&gt;
    &lt;property name="keylength" value="256" /&gt;                         &lt;5&gt;
    &lt;property name="duration" value="86400000" /&gt;                     &lt;6&gt;
&lt;/crypto-service&gt;
</code></pre>
<ul>
<li>&lt;1> custodian PGP id, there can be many <code>custodian</code> entries.</li>
<li>&lt;2> path to the public keyring.</li>
<li>&lt;3> path to the password-protected private keyring.</li>
<li>&lt;4> if lazy=true, a key is generated the first time we call <code>aesEncrypt</code>, otherwise, a new one is created at service start.</li>
<li>&lt;5> key length defaults to 256. Can be reduced if AES-256 is not supported by the JVM due to export restrictions.</li>
<li>&lt;6> key duration</li>
</ul>
<p>This allows jPOS nodes to encrypt data securely without storing the encryption key to disk.</p>
<p><strong>NOTE</strong>: The transient encryption key is still in memory, so core dumps and swap should be<br />
disabled at the operating system level. This approach is still more secure<br />
than obfuscating encryption keys.</p>
<p>Decryption &#8212; that can of course run in a different node, at a different time &#8212; requires<br />
access to the private keyring, with its optional password. Said password can be entered<br />
manually, obtained from a remote service or HSM, etc. and it&#8217;s a two step process.</p>
<p>First the key has to be <em>loaded</em> into memory, using the <code>loadKey</code> method. Once the key<br />
is loaded, the <code>aesDecrypt</code> can be called.</p>
<p>These are the method&#8217;s signatures:</p>
<pre><code>public void loadKey (String jobId, String keyId, char[] password) throws Exception;
public byte[] aesDecrypt (String jobId, String keyId, byte[] encoded) throws Exception;
</code></pre>
<p>Here <code>keyId</code>, <code>password</code>, and <code>encoded</code> cryptogram don&#8217;t require too much explanation, but <code>jobId</code> does and here is the rationale. We could have a one-shot <code>aesDecrypt</code> method accepting the private key password, but decrypting the AES-256 key using PGP is an expensive operation. In situations where you have extract a daily file, probably encrypted by just a handful keys, you don&#8217;t want to decrypt the key on every <code>aesDecrypt</code> call. We don&#8217;t want to expose the key to the caller either, so the CryptoService keeps it in a private field. In order to do that, <code>loadKey</code> caches the key (until it&#8217;s unloaded), so it&#8217;s cheap to call <code>loadKey</code> followed by <code>aesDecrypt</code>, after the first call where the key is actually decrypted, subsequent calls will be pretty fast.</p>
<p>In order to protect different clients from accessing keys loaded by other ones, we use a <code>jobId</code> that can be something as simple as a <code>UUID</code> or any nonce, only known to the caller. That <code>jobId</code> can then be used to <code>unload</code> those keys, using the <code>unloadKey</code> and <code>unloadAll</code> methods:</p>
<pre><code>public boolean unloadKey (String jobId, String keyId);
public void unloadAll(String jobId);
</code></pre>
<p>There&#8217;s also a no-args <code>unloadAll()</code> that unloads all keys, and should be used with care.</p>
<p><strong>NOTE</strong>: In order to simplify development and testing, and eventually to troubleshoot problems, we&#8217;ve also created a couple of CLI commands: <code>aesencrypt</code> and <code>aesdecrypt</code>.</p>
<p><strong>TIP</strong>: If you&#8217;re accessing the CLI using the command line <code>q2 --cli</code>, remember that the default <code>deployDir</code> is <code>deploy-cli</code> instead of <code>deploy</code>. You need a copy (or symlink) of <code>25_cryptoservice.xml</code> in that directory. If you <code>ssh</code> to a running Q2 to reach the CLI, then you can ignore this tip.</p>
<p>For up-to-date information about this CryptoService module, please see the <a href="http://jpos.org/doc/jPOS-EE.pdf">jPOS-EE</a> guide.</p>
]]></content:encoded>
			</item>
		<item>
		<title>TxnId</title>
		<link>http://jpos.org/blog/2017/10/txnid/</link>
		<pubDate>Fri, 27 Oct 2017 01:59:09 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=927</guid>
		<description><![CDATA[There&#8217;s a new handy org.jpos.transaction.TxnId class in the jPOS-EE txn module that can be used to generate transaction ids in multi-node systems. The id is composed of: 1-digit century 2-digits year 3-digits day of year 5-digits second of day 3-digits node id 5-digits transaction id A typical ID long value would look like this: 173000702600000001, [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>There&#8217;s a new handy <code>org.jpos.transaction.TxnId</code> class in the jPOS-EE <code>txn</code> module that can be used to generate transaction ids in multi-node systems.</p>
<p>The id is composed of:</p>
<ul>
<li>1-digit century</li>
<li>2-digits year</li>
<li>3-digits day of year</li>
<li>5-digits second of day</li>
<li>3-digits node id</li>
<li>5-digits transaction id</li>
</ul>
<p>A typical ID long value would look like this: <code>173000702600000001</code>, and the <code>toString()</code> method would show as <code>017-300-07026-000-00001</code> and the <code>toRrn()</code> method would return <code>1bbfmplq9la9</code>.</p>
<p><code>TxnId</code> also has a handy <code>toRrn()</code> method that can be used to create (and parse) 12-characters strings suitable to be used as retrieval reference numbers.</p>
<p><code>TxnId</code> can be used instead of UUIDs. It puts less pressure in the database index and provides chronological order.</p>
<p><strong>NOTE:</strong> The last two groups, <code>node-id</code> and <code>transaction-id</code> are supposed to be unique. <code>transaction-id</code> is easy to get from the transaction manager and <code>node-id</code> is a tricky one, user has to ensure each node has a unique <code>node-id</code> to avoid collisions.</p>
<p>Sample usage:</p>
<p><code>java<br />
TxnId txnId = TxnId.create(DateTime.now(), 0, id);</code></p>
<ul>
<li><a href="https://github.com/jpos/jPOS-EE/blob/master/modules/txn/src/main/java/org/jpos/transaction/TxnId.java">Code</a></li>
<li><a href="https://github.com/jpos/jPOS-EE/blob/master/modules/txn/src/test/java/org/jpos/transaction/TxnIdTest.java">Unit Test</a></li>
<li><a href="http://jpos.org/doc/jPOS-EE.pdf">Documentation</a> (see &#8216;Core Modules&#8217;)</li>
</ul>
]]></content:encoded>
			</item>
		<item>
		<title>jPOS 2.1.0 has been released</title>
		<link>http://jpos.org/blog/2017/05/jpos-2-1-0/</link>
		<pubDate>Sat, 27 May 2017 18:06:17 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=914</guid>
		<description><![CDATA[jPOS 2.1.0 has been released, new development version is now 2.1.1-SNAPSHOT Please see the ChangeLog. Remember we are using Semantic Versioning so the change from 2.0.10 to 2.1.0 means a full rebuild has to be done in your applications. Some of the most notable changes are: TransactionContext is now backed by a Map&#60;String,Object&#62; instead of [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>jPOS 2.1.0 has been released, new development version is now 2.1.1-SNAPSHOT</p>
<p>Please see the <a href="http://jpos.org/wiki/ChangeLog">ChangeLog</a>.</p>
<p>Remember we are using <a href="http://semver.org">Semantic Versioning</a> so the change from 2.0.10 to 2.1.0 means a full rebuild has to be done in your applications. Some of the most notable changes are:</p>
<ul>
<li>TransactionContext is now backed by a <code>Map&lt;String,Object&gt;</code> instead of the old <code>Map&lt;Object,Object&gt;</code> so that needs review</li>
<li>Some methods that used to throw ISOException are not throwing it anymore</li>
</ul>
<p>Other than those two minor changes, jPOS 2.1.0 has a large number of improvements, including TransactionManager metrics, new <code>org.jpos.rc</code> package, bug fixes and improved TransactionManager capacity.</p>
<p>jPOS-EE 2.2.4 has been released as well, new development versions are <code>jPOS 2.1.0-SNAPSHOT</code> and <code>jPOS-EE 2.2.5-SNAPSHOT</code>.</p>
<p>See <a href="http://jpos.org/resources">Resources Page</a> for details.</p>
]]></content:encoded>
			</item>
		<item>
		<title>Tutorial &#8211; Writing a gateway the jPOS way</title>
		<link>http://jpos.org/blog/2017/05/jpos-tutorial-writing-a-jpos-gateway/</link>
		<pubDate>Mon, 08 May 2017 14:51:44 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=898</guid>
		<description><![CDATA[I get to see dozens of third party jPOS gateway implementations just using 5% of jPOS capabilities. People download jPOS just to use the ISO-8583 packing/unpacking and sometimes they don&#8217;t even get to use the channels, multiplexers, servers, transaction manager. I see developers trying to stay away from Q2 probably because they don&#8217;t know it, [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I get to see dozens of third party jPOS gateway implementations just using 5% of jPOS capabilities.</p>
<p>People download jPOS just to use the ISO-8583 packing/unpacking and sometimes they don&#8217;t even get to use the channels, multiplexers, servers, transaction manager. I see developers trying to stay away from Q2 probably because they don&#8217;t know it, but it&#8217;s quite simple to use.</p>
<p>So I wrote a little tutorial, <a href="http://jpos.org/doc/tutorials/jpos-gateway.pdf">http://jpos.org/doc/tutorials/jpos-gateway.pdf</a> that walks you through the process of installing jPOS and writing a production grade gateway capable of processing thousands of transactions per second.</p>
<p>The tutorial has two parts, first you get it running (takes about 5 minutes), then the second part explains why that very simple configuration works.</p>
<p>The second part has plenty of links to the jPOS programmer&#8217;s guide documentation (freely available), while it&#8217;s just a couple pages, understanding it and following the links may take some more time and may raise some questions that we&#8217;ll be happy to answer.</p>
]]></content:encoded>
			</item>
		<item>
		<title>Investor&#8217;s Dilemma : How do I Handle Unlicensed Copies of AGPL Software in a Portfolio Company</title>
		<link>http://jpos.org/blog/2017/04/investor-dilema/</link>
		<pubDate>Mon, 17 Apr 2017 18:07:02 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=888</guid>
		<description><![CDATA[Every once in a while we receive a request from an investor or private equity firm who, in the process of conducting due-diligence on an existing or established potential portfolio company, encounters an unlicensed copy of jPOS. Often the company has released a commercial product which incorporates this unlicensed software. Investors want to know, how [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Every once in a while we receive a request from an investor or private equity firm who, in the process of conducting due-diligence on an existing or established potential portfolio company, encounters an unlicensed copy of jPOS. Often the company has released a commercial product which incorporates this unlicensed software. Investors want to know, how should we proceed and what are the responsibilities of the company vis-à-vis the license and source code?</p>
<p>The easiest and first answer is of course, the company should purchase a license and not rely on pirated software to conduct their business. The more subtle question is what does it imply when a start-up is willing to pirate software which is intended to be reasonably priced and positioned to benefit the authors and the overall Fintech software community as a whole?</p>
<p>Isn&#8217;t it risky to partner with a company that disregards good business practices, either because of bad faith or negligence?</p>
<p>If it were me, I&#8217;d invest somewhere else!</p>
]]></content:encoded>
			</item>
		<item>
		<title>jPOS-EE BinLog module</title>
		<link>http://jpos.org/blog/2017/03/jpos-ee-binlog-module/</link>
		<pubDate>Fri, 03 Mar 2017 20:43:32 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=879</guid>
		<description><![CDATA[jPOS-EE has a new binlog module, a general purpose binary log that can be used as a reliable event store. The jPOS BinLog has the following features: multiple readers and writers can be used from the same JVM multiple readers and writers can be used from different JVMs Here is a sample Writer: File dir [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>jPOS-EE has a new <a href="https://github.com/jpos/jPOS-EE/tree/master/modules/binlog">binlog module</a>, a general purpose binary log that can be used as a reliable event store.</p>
<p>The jPOS BinLog has the following features:</p>
<ul>
<li>multiple readers and writers can be used from the same JVM</li>
<li>multiple readers and writers can be used from different JVMs</li>
</ul>
<p>Here is a sample Writer:</p>
<pre><code>File dir = new File("/tmp/binlog");
try (BinLogWriter bl = new BinLogWriter(dir)) {
    bl.add( ... ); // byte array
    bl.add( ... ); // byte array
    bl.add( ... ); // byte array
}
</code></pre>
<p>and a sample Reader:</p>
<pre><code>File dir = new File("/tmp/binlog");
try (BinLogReader bl = new BinLogReader(dir)) {
    while (bl.hasNext()) {
        byte[] b = bl.next().get();
        // do something with the byte[]
    }
} 
</code></pre>
<p>The <code>BinLogReader</code> implements an <code>Iterator&lt;BinLog.Entry&gt;</code>. Each <code>BinLog.Entry</code> has two main methods:</p>
<ul>
<li><code>BinLog.Rer ref()</code></li>
<li><code>byte[] get()</code></li>
</ul>
<p>While iterating over a BinLog, it might make sense to persistently store its <code>BinLog.Ref</code> in order to be able to restart the iterator at a given point if required (this is useful if using the BinLog to implement a Store and Forward.</p>
<p>The <code>BinLogReader</code> has two constructors:</p>
<ul>
<li><code>BinLogReader(File dir)</code></li>
<li><code>BinLogReader(File dir, BinLog.Ref ref)</code></li>
</ul>
<p>the latter can be used to restart the iterator at a given reference point obtained from a previous run.</p>
<p>In addition to the standard <code>hasNext()</code> method required by the <code>Iterator</code> implementation, <code>BinLogReader</code> also has a <code>hasNext(long millis)</code> method that waits a given number of milliseconds once it reaches the end of the log, attempting to wait for a new entry to be available.</p>
<p>The goal behind the BinLog implementation is to have a future proof file format easy to read from any language, 10 years down the road. We found that the Mastercard simple IPM file format, that&#8217;s basically a two-byte message length followed by the message itself was suitable for that. The payload on each record can be ISO-8583 (like Mastercard), JSON, FSDMsg based, Protocol buffers or whatever format the user choose.</p>
<p>But that format isn&#8217;t crash proof. If a system crashes while a record is being written to disk, the file can get easily corrupted. So we picked some ideas from Square&#8217;s <em>tape</em> project that implements a highly crash proof on-disk persistent circular queue using a very small header. Tape is great and we encourage you to consider it instead of this binlog for some use cases, but we didn&#8217;t want a circular queue, we wanted a place to securely store events for audit or store and forward purposes, and we also wanted to be able to access the same binlog from multiple JVMs with access to the same file-system, so we had to write our own.</p>
<p>The on-disk file format looks like this:</p>
<pre><code>Format:
256 bytes Header
... Data
... Data

Header format (256 bytes):
4 bytes header length
2 bytes version
2 bytes Status (00=open, 01=closed)
8 bytes Last element position
4 bytes this log number
4 bytes next log number
232 bytes reserved

Element:
4 bytes Data length
...     Data
</code></pre>
<p>Each record has a length prefix (four bytes in network byte order) followed by its data. The header has a fixed length of 256 bytes but we found useful to make it look like a regular record too by providing its length at the very beginning. An implementation in any language reading a jPOS binlog can just be programmed to skip the first record.</p>
<p>At any given time (usually at end of day), a process can request a <em>cut-over</em> by calling the <code>BinLogWriter.cutover()</code> method in that case, all writers and readers will close the current file and move to the next one (Readers can choose to not-follow to the next file, for example while producing daily extracts).</p>
<p>In order to achieve file crash resilience, each write does the following:</p>
<ul>
<li>Lock the file</li>
<li>Write the record&#8217;s length and data</li>
<li>Sync to disc</li>
<li>Write the last element position to the header</li>
<li>Sync to disc</li>
<li>Unlock the file</li>
</ul>
<p>In an MBP with SDRAM we&#8217;ve managed to achieve approximately 6000 writes per second. On an iMac with regular disk the numbers go down to approximately 1500 writes per second for regular ISO-8583 message lengths (500..1000 bytes per record).</p>
<p>Due to the fact that the header is small enough to fit in an operating system block, the second write where we place the last element position happens to be atomic. While this works OK for readers and writers reading the file from different JVMs, that&#8217;s not the case for readers and writers running on the same JVM, even if they use a different file descriptor to open the file, the operating system stack has early access to the header that under high concurrency can lead to garbage values, that&#8217;s the reason the code synchronizes on a <code>mutex</code> object at specific places.</p>
<h2>Supporting CLI commands</h2>
<p>The <code>binlog</code> CLI command is a subsystem that currently have two commands:</p>
<ul>
<li>monitor (to visually monitor a binlog)</li>
<li>cutover (to force a cutover)</li>
<li>exit (builtin command)</li>
</ul>
<p><code>binlog</code> accepts a parameter with the binlog&#8217;s path, i.e: <code>binlog /tmp/binlog</code></p>
<p>So a cutover can be triggered from cron using the following command:</p>
<pre><code>q2 --command="binlog /tmp/binlog; cutover; exit; shutdown --force"
</code></pre>
]]></content:encoded>
			</item>
		<item>
		<title>jPOS 2.0.10 has been released</title>
		<link>http://jpos.org/blog/2017/01/jpos-2-0-10-has-been-released/</link>
		<pubDate>Mon, 02 Jan 2017 00:36:21 +0000</pubDate>
		<dc:creator><![CDATA[apr]]></dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpos.org/blog/?p=871</guid>
		<description><![CDATA[jPOS 2.0.10 has been released, new development version is now 2.1.0-SNAPSHOT This release upgrades JLine to 3.0.0, adds new CLI commands and subsystems, upgrades Gradle to 3.1.0, allows license to be read from external file and removes double-logging in PADChannel. The main reason for this small release is to flush small enhancements before we make [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>jPOS 2.0.10 has been released, new development version is now 2.1.0-SNAPSHOT</p>
<p>This release upgrades JLine to 3.0.0, adds new CLI commands and subsystems, upgrades Gradle to 3.1.0, allows license to be read from external file and removes double-logging in PADChannel. The main reason for this small release is to flush small enhancements before we make some bigger changes to the TransactionManager with improved audit logging (those are already available in 2.1.0-SNAPSHOT). It also updates the copyright year to 2017 and changes the copyright owner to the new entity jPOS Software SRL.</p>
<p>Starting with this release we&#8217;ll move to semantic versioning, so next release is going to be 2.1.0 and requires a full clean build of your projects in order to make sure some of the API changes don&#8217;t break your system.</p>
<p>see <a href="http://jpos.org/wiki/ChangeLog">ChangeLog</a> for details.</p>
]]></content:encoded>
			</item>
	</channel>
</rss>
