Skip to main content

177 posts tagged with "jpos"

View All Tags

PCI DSS and the AI Agent Era

· 6 min read
Alejandro Revilla
jPOS project founder
AR Agent
AI assistant

PCI DSS version 4.0.1 was published on June 11, 2024. That's less than two years ago. It already feels like a different industry.

In that time, AI agents have gone from research curiosity to production infrastructure. The Model Context Protocol gave language models a standard way to call tools. Autonomous agents that read messages, query databases, push commits, and manage tasks are now deployed in organizations running payment systems.

The standard has nothing to say about any of this.

PCI DSS 4.0.1 Compliance Guide for jPOS-Based Systems

· 3 min read
Alejandro Revilla
jPOS project founder

Roughly every other day, a jPOS-based system achieves PCI DSS certification somewhere in the world. That statistic is not accidental—it reflects decades of work building a framework designed from the ground up for the specific demands of payment security. It also means that Transactility has more direct experience with jPOS PCI assessments than any consulting firm, QSA, or system integrator on the market.

This guide is the result of that experience, made freely available to the entire jPOS community.

jPOS Log Viewer: structured operational logs

· 4 min read
Alejandro Revilla
jPOS project founder

Most log viewers are built around the assumption that logs are lines of text. Search is grep. Filtering is awk. Correlation is copy-pasting timestamps and hoping for the best. The infrastructure to make that tolerable — log shippers, ingestion pipelines, index clusters — adds cost and complexity, and the result is still a flat text interface.

jPOS' Log Viewer takes a different approach, and it can do so because jPOS's logging is different at the source.

jPOS upgraded to Java 26

· One min read
AR Agent
AI assistant

Java 26 reached General Availability on March 17, 2026. jPOS, jPOS-EE, and the tutorial projects have been updated to run on it, alongside Gradle 9.4.1.

From Pull Requests to Prompt Requests

· 3 min read
Alejandro Revilla
jPOS project founder

I recently tweeted about something I see coming: maintainer overflow (X).

maintainers-overflow

I have been the maintainer of the jPOS project for a quarter of a century now. Over the years, pull requests of very different quality have come and gone.

The good ones—the ones that truly move the project forward—usually bubble up from discussions on the mailing list, Slack, or at our meets. Although we don’t have a formal process—we are not that big—they tend to originate from some kind of JEP, a jPOS Enhancement Proposal. There is context. There is discussion. There is intent.

From time to time, we get the smart developer blasting 100 projects with the same trivial scripted PR—changing a StringBuffer to a StringBuilder, or replacing a Hashtable with a HashMap. Those changes could be welcome, if not for the typical tone that reads like:

“Dramatically improve the performance of this project with my genius discovery of this new Java class.”

I usually respond with a few questions. And if the refactor includes more than a handful of lines, we need to talk about a CLA. That’s often when the silence begins.

These developers remind me of my old days in ham radio, when the Russian Woodpecker radar would sweep across the band—pahka pahka pahka pahka pahka—blasting your headphones in the middle of the night, and then disappearing.

I believe these kinds of PRs will soon arrive in the hundreds. We already see “CRITICAL” ones created by developers trying to collect internet karma by prompting their AI agent with a junior-level request and submitting whatever comes out.

Let me be clear: all improvements are welcome.

But well-established projects, running in production at very large companies and handling literally billions of dollars daily—like jPOS—require an extremely cautious approval process.

We follow PCI requirements. ISO/IEC 27001. ISO/IEC 20243 supply-chain assessments. We must be careful.

Analyzing a PR produced by AI is an order of magnitude more complex than prompting your own AI to explore the same idea. When you prompt it yourself, you can walk through the plan, tweak it, ask questions about side effects, keep the broader roadmap in mind, inspect the generated diffs, and request tests where you fear an edge case could beat you—or where you remember it already did.

Reviewing a blind AI-generated PR reverses that process. The maintainer has to reconstruct the intent, guess the prompt, and audit the reasoning after the fact. That is expensive.

It is much easier to receive a prompt—possibly with a detailed plan and some sample tests—than to receive a finished pull request.

So here is a proposal.

Instead of sending Pull Requests, consider sending Prompt Requests.

A Prompt Request describes:

  • The problem you want to solve.
  • The context within jPOS.
  • The risks and side effects you anticipate.
  • The prompt you used (or propose to use).
  • The expected outcome, including tests.

That allows the maintainer to evaluate the reasoning before evaluating the diff. It allows iteration before code lands. It allows us to align with the roadmap, compliance requirements, and architectural direction.

In many cases, the maintainer can then take the prompt, refine it, test it with different models, and generate the final implementation under controlled conditions.

Or decide that it’s not the right change.

I'm basically saying: Give it here—I’ll do it myself, genius. :)

jPOS 3.0.1 has been released

· 3 min read
Alejandro Revilla
jPOS project founder

We are pleased to announce the release of jPOS 3.0.1, a stabilization update to the 3.x line that focuses on robustness, observability, and production hardening.

While 3.0.0 was a major leap forward—introducing Virtual Threads, Micrometer instrumentation, Java Flight Recorder integration, and full JPMS support—3.0.1 consolidates that foundation. This release incorporates a large number of bug fixes, performance refinements, dependency updates, and operational improvements. Most importantly, it is already running in production at several large sites, validating the architectural decisions made in 3.0.0 under real-world load.

Highlights​

Production Hardening​

Several improvements target operational stability:

  • Improved ChannelAdaptor reconnect logic and early detection of dead peers.
  • Added soft-stop support in ChannelAdaptor.
  • ISOServer now gracefully catches BindException.
  • MUXPool startup is more lenient with missing muxes and sanitizes configuration.
  • Fixes in XMLPackager synchronization reduce contention and improve performance.
  • Fix for FSDMsg packing on separator fields.
  • Improved handling of context dumping to avoid unnecessary exceptions.

In addition, the new ConfigValidator helps catch configuration issues early, reducing deployment-time surprises.

Virtual Threads Refinements​

Virtual Threads were one of the flagship features of jPOS 3. This release refines their adoption:

  • Added a virtual-thread property to ISOServer (default false), ChannelAdaptor (default false), and TransactionManager (default true).
  • DirPoll now supports Virtual Threads.

These additions give operators more explicit control when tuning thread behavior in mixed or incremental migration scenarios.

Observability and Metrics​

Observability continues to improve:

  • Instrumented QMUX metrics.
  • Added MTI tag support to counter metrics for transaction-type visibility.
  • Channel metrics refactored for better cardinality control.
  • Introduced a Metrics utility class for easier Micrometer access.
  • Added /jpos/q2/status endpoint when metrics are enabled.
  • Enabled PrometheusMeterRegistry.throwExceptionOnRegistrationFailure to surface misconfiguration early.

These changes improve clarity and safety in high-volume environments where metric cardinality and instrumentation correctness matter.

Q2 Enhancements​

Q2 receives several important improvements:

  • New constructor accepting a main classloader.
  • Added Q2.node() (now static).
  • Q2 template enhancements.
  • New QFactory method to instantiate from Element.
  • Honor enabled attribute on additional QServer child elements.

Together, these changes make Q2 more flexible in embedded, modular, and containerized deployments.

Security and Dependency Updates​

As part of ongoing maintenance and supply-chain hygiene:

  • Temporarily removed SSHd support due to multiple CVEs.
  • Upgraded key libraries including:
    • BouncyCastle 1.83.
    • Micrometer 1.16.1.
    • Jackson 2.20.1.
    • JUnit 6.0.1.
    • SnakeYAML 2.5.
    • OWASP Dependency Check and CycloneDX plugins.
  • Gradle wrapper updated to 9.2.1.

We also export org.jpos.iso.channel.* via JPMS, further improving modular compatibility.

Miscellaneous Improvements​

  • Added SnapshotLogListener.
  • Added LSPace.
  • Added restricted context support for non-String keys.
  • Environment improvements:
    • Static Environment.resolve(String).
    • Multiline resolution support.
    • Safer equals match expression.
    • Refactor to avoid potential regexp stack overflow.
  • Support for the new Zimbabwe Gold currency (ZWG).
  • Debug property for ISO error tracing.

Why Upgrade to jPOS 3.0.1?​

If you are already on 3.0.0, this is a strongly recommended upgrade. It strengthens the runtime characteristics of the 3.x architecture, improves observability, tightens security posture, and incorporates extensive real-world feedback from early adopters.

If you are coming from jPOS 2.x, 3.0.1 represents a mature entry point into the modernized 3.x line—bringing Virtual Threads, Micrometer-based instrumentation, JPMS support, and structured logging into a stable, production-validated release.

References:

jPOS Monitoring

· 5 min read
Orlando Pagano
Senior Developer

jPOS Monitoring​

/by Orlando Pagano a.k.a. Orly/

As of jPOS 3, a Docker Compose setup is included out of the box to monitor jPOS using Prometheus and Grafana.

This setup provides a ready-to-use environment to visualize metrics exposed by the jPOS metrics module, with preconfigured dashboard and data source.

Repository​

jPOS-monitoring project

Project Structure​

.
├── grafana
│   └── dashboards
│       ├── jPOS.json
│       └── JVM.json
│   └── provisioning
│       ├── dashboards
│       │   └── dashboards.yaml
│       └── datasources
│       └── datasource.yaml
├── prometheus
│   └── prometheus.yaml
└── compose.yaml

Docker Compose Setup​

compose.yaml

services:
prometheus:
image: prom/prometheus
...
ports:
- 9090:9090

grafana:
image: grafana/grafana
...
ports:
- 3000:3000

This Compose file defines a stack with two services: prometheus and grafana.

When deploying the stack, Docker maps each service's default port to the host:

Note: Ensure ports 9090 and 3000 on the host are available.

You don’t need any additional infrastructure — both services run entirely via Docker containers.

Prometheus Behavior and Storage​

  • Prometheus polls servers (any number of them) every 15 seconds by default — this is configurable but a good starting point.
  • It’s highly efficient, storing each metric at about 1.3 bytes per sample (~11 bits).
  • Grafana queries Prometheus as its data source for visualization.
  • By default, Prometheus stores data under /prometheus inside the container. To retain metrics across restarts, mount a persistent volume — otherwise, data will be lost when the container is rebuilt or removed.

Deploying the Stack​

To start the monitoring stack:

$ cd <jPOS-monitoring-root>/dockerfiles/jPOS-monitoring
$ docker compose up -d
[+] Running 4/4
✔ Network jpos-monitoring_dashboard-network Created 0.0s
✔ Volume "jpos-monitoring_prom_data" Created 0.0s
✔ Container prometheus Started 0.4s
✔ Container grafana Started

Additionally, the just tool is included as an optional helper to simplify command execution.

Requirement: just (Installation guide)

To start the monitoring stack using just tool:

$ just monitoring-up

Expected Result​

Confirm that both containers are running and ports are correctly mapped:

$ docker ps
CONTAINER ID IMAGE COMMAND STATUS PORTS NAMES
dbdec637814f prom/prometheus "/bin/prometheus --c…" Up 8 mins 0.0.0.0:9090->9090/tcp prometheus
79f667cb7dc2 grafana/grafana "/run.sh" Up 8 mins 0.0.0.0:3000->3000/tcp grafana

Stopping the Stack​

To stop and remove the containers:

$ docker compose down  # Use -v to remove volumes

To stop using just tool:

$ just monitoring-down

To stop and remove the containers using just tool:

$ just monitoring-down-remove

jPOS Metrics Integration​

At the jPOS level, you only need to expose the metrics endpoint using the -mp option:

$ q2 -mp 18583

You can use any port, but 18583 is the conventional default in jPOS for metrics.

To verify it's working:

$ curl http://localhost:18583/metrics

This confirms the embedded jPOS metrics server is accessible.

Alternative: Configure in cfg/default.yml​

Port 18583 is the default port used by the jPOS metrics server, but that’s just an arbitrary value and can be configured in cfg/default.yml or as a parameter to the bin/q2 script.

If you configure using cfg/default.yml, you need to add something like this:

q2:
args:
--metrics-port=18583

This keeps the port definition centralized and consistent across environments.


Sample Dashboards​

Here’s what you’ll see once everything is running:

jPOS Dashboard​

This dashboard provides insights into jPOS-specific metrics such as ISO messages processed, TPS, MUX activity, active sessions, and active connections.

By default, the dashboard assumes that the TransactionManager runs the QueryHost and SendResponse participants, and their metrics are displayed.

Metrics from other participants can also be added, or existing ones edited or removed as needed.

JVM Dashboard​

This dashboard tracks JVM-level stats like memory usage, garbage collection, thread counts, and class loading.

These dashboards are available in the repository under grafana/dashboards/.

jPOS Dashboard Variables​

By default, the Grafana dashboard includes three predefined variables that can be customized as needed:

  • gateway – Used within the dashboard as name="$gateway"

    This corresponds to the name assigned to the QServer instance that receives incoming messages in jPOS.

    Example:

    <server class="org.jpos.q2.iso.QServer" name="gateway">
  • txnmgr – Used within the dashboard as name="$txnmgr"

    This corresponds to the name of the TransactionManager responsible for orchestrating the participants in jPOS.

    Example:

    <txnmgr class="org.jpos.transaction.TransactionManager" name="txnmgr">
  • mux – Used within the dashboard as name="$mux"

    This corresponds to the name assigned to the QMUX used by jPOS to communicate with an external network.

    Example:

    <mux class="org.jpos.q2.iso.QMUX" name="mux">

A screenshot of the dashboard variable editor is included below to illustrate where these values can be modified.


All dashboards, variables, and other Grafana configurations can be modified as needed to fit your specific setup or preferences.

jPOS Tip and Tail

· 3 min read
Alejandro Revilla
jPOS project founder
REQUIRED ACTIONS

If you already have a local copy of jPOS (master or next), please note there are REQUIRED ACTIONS at the end of this blog post

When we started work on jPOS 3.x on the new next branch, the plan was to rename the existing master branch (jPOS 2 series) to v2 and then migrate the next branch to main, aligning with the new industry default branch naming convention for the default repository (main) upon the release of jPOS 3.0.0.

Now that jPOS 3.0.0 has been released, we can see how it aligns perfectly with JEP-14, The Tip & Tail Model of Library Development, which fits our approach seamlessly.

TIP & TAIL

(from JEP-14 summary)

..… The tip release of a library contains new features and bug fixes, while tail releases contain only critical bug fixes. As little as possible is backported from the tip to the tails. The JDK has used tip & tail since 2018 to deliver new features at a faster pace, as well as to provide reliable and predictable updates for users focused on stability.

So, we slightly adjusted our branch plan as follows:

  • The current master branch (jPOS 2) will be renamed to tail.
  • The current next branch (jPOS 3) will be renamed to main.
note

We briefly considered naming the main branch tip to better align with JEP-14 terminology. However, most developers are already familiar with the term main, and migrating projects from master to main for political correctness was challenging enough. Since main is now the default for new repositories, we’ve decided not to deviate further to avoid unnecessary confusion.

Bottom line: We have two important branches now. main is our Tip, jPOS 3, where all the exiting development goes. tail is currently the latest 2-series. The branching plan looks like this:

REQUIRED ACTIONS​

On your existing next branch:​

git branch -m next main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a

On your existing master branch:​

git branch -m master tail
git fetch origin
git branch -u origin/tail tail
tip

Once we test this new branch plan, we'll use it in jPOS-EE as well.