Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

master: Add annotation functionality to jPos participant. #576

Open
wants to merge 8 commits into
base: tail
Choose a base branch
from

Conversation

espaillato
Copy link
Contributor

@espaillato espaillato commented Dec 19, 2023

Application developers are very familiar with writing APIs and using annotations to wire things together. In addition, IoC/Dependency Injection is an accepted standard across frameworks. JPos, on the other hand, uses a simple 2-phase commit interface to string together units of work called participants. Participants can be considered like filters strung together to perform a transaction in the web world.

While writing participants in jPos is simple, the interface is straightforward. However, it has some drawbacks, mainly due to two factors: the lack of IoC and the lack of a contract. This attempts to introduce IoC and a verifiable contract on the TransactionManager using annotations to enable parameters and return types on the prepare method. This should make JPos more developer-friendly by adding auto-binding of parameters.

For example, We convert the standard participant entry point int doPrepare(long id, Context ctx) to any custom method with parameter binding.

  @Result(CARD)
  protected Card findCard(@ContextKey(PAN) String pan, @ContextKey DB db) throws BLException {

This increases the code's readability and testability by specifying a contract and doing the injection at the transaction manager level. In this case, findCard only accesses PAN, needs access to the CardDAO object and returns a Card object. When testing, you only need to test card present or missing scenarios because you know this method cannot have any other side effects.

The annotations should be more familiar to any developer comfortable with API development using any current framework.

The power of this comes in with the contract. Suppose I wanted to boondoggle extra functionality into the FindCard participant. I can do so by using the Context, which can have side effects throughout the code without changing any test. However, with the annotated participant, the only thing that can be returned by the FindCard participant is the Card object, so no changes to the contract are allowed without a change to the signature.

@aVolpe
Copy link
Contributor

aVolpe commented Dec 19, 2023

After some testing, some minor observations:

  1. A NameRegistrar entry can be created after the transaction manager's setup, so the registrar arguments should be resolved in the call to prepare and not in the configuration.
  2. To test this API better, this can be put entirely in a separate module since the only interaction point with the rest of jPos is in the transaction manager. This will make this easy to test in current projects.

This is a very cool idea and implementation!

@ar
Copy link
Member

ar commented Dec 20, 2023

... so the registrar arguments should be resolved in the call to prepare and not in the configuration.

Remember the participants use the Flyweight pattern. It's cheaper to do stuff at configuration time than prepare time.

@espaillato
Copy link
Contributor Author

  1. so the registrar arguments should be resolved in the call to prepare and not in the configuration.

At configuration, we check for the presence of the entry in NameRegistrar to so the name resolution. This is to prevent the transaction manager to be initialized without being fully functional. If you have a dependency on something in NameRegistrar, you should have it initialize before the transaction manager. Having said that, the actual lookup/binding NameRegistrar.get... happens at runtime. This is because an entry in NameRegistrar can be changed, i.e. xml is touched, so we always want to get the latest from the NameRegistrar.

@alcarraz
Copy link
Contributor

At configuration, we check for the presence of the entry in NameRegistrar to so the name resolution. This is to prevent the transaction manager to be initialized without being fully functional. If you have a dependency on something in NameRegistrar, you should have it initialize before the transaction manager. Having said that, the actual lookup/binding NameRegistrar.get... happens at runtime. This is because an entry in NameRegistrar can be changed, i.e. xml is touched, so we always want to get the latest from the NameRegistrar.

The issue with checking the presence at config time, is that many, if not most, of the jPOS standard components are registered in NameRegistrar in the start phase; this would make the check to fail in the config time, which is at the init phase. Validation should be controlled by a boolean argument of the annotation. Thankfully the new eager start support now allows you to eager start those dependencies, but I believe that that validation should be optional, to not induce people to always force the eager start in order to use this feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants