Skip to content

Fix Jakarta 3.1 compliance for Character property types#1736

Merged
jeanouii merged 7 commits intoapache:mainfrom
pradeep85841:fix/jakarta-31-property-compliance
Mar 12, 2026
Merged

Fix Jakarta 3.1 compliance for Character property types#1736
jeanouii merged 7 commits intoapache:mainfrom
pradeep85841:fix/jakarta-31-property-compliance

Conversation

@pradeep85841
Copy link
Contributor

This PR addresses a spec compliance issue in ActiveMQMessage regarding allowed property types.

TCK Alignment: Updated checkValidObject to reject Character types when isNestedMapAndListEnabled is set to false, as required by the Jakarta Messaging 3.1 specification.

Backward Compatibility: Maintained support for Character types when the legacy flag is true (default) to prevent regressions for existing users.

Validation: Added unit tests to verify that MessageFormatException is correctly thrown in strict mode while verifying successful property assignment in legacy mode.

@jbonofre jbonofre self-requested a review March 7, 2026 15:53
@jbonofre
Copy link
Member

jbonofre commented Mar 7, 2026

In order to be Jakarta Messaging 3.1 fully compliant, I would suggest to set nestedMapAndListEnabled to false by default, in order to not accept Character.

@pradeep85841
Copy link
Contributor Author

Set nestedMapAndListEnabled to false by default for Jakarta 3.1 compliance

Copy link
Contributor

@jeanouii jeanouii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think changing the default from true to false is impacting for customers because it does not only impact Character but also Map and List.
The change in the connection is incomplete if we want to do so, we would need also to change the factory.
If everyone agrees to change default, I don't have a special opinion on this, we should mention it's to align with specification by default and it needs to be clear in the documentation and in the release notes.

Finally, I'd put some more love in the tests if you don't mind.
The embedded broker is started automatically by the factory but it's not stopped. That can cause flaky tests. Also the connections should also be using try-with-resources. This is small non blocking comment.

Overall, good job with the PR

private long optimizeAcknowledgeTimeOut = 0;
private long optimizedAckScheduledAckInterval = 0;
private boolean nestedMapAndListEnabled = true;
private boolean nestedMapAndListEnabled = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this has any effect. The factory creating the connection defaults to true and overrides this value I think. To be verified and discarded if I'm not correct.

@pradeep85841
Copy link
Contributor Author

pradeep85841 commented Mar 11, 2026

Thank you @jeanouii for the detailed review and suggestions. I agree with your points.

I will update the ActiveMQConnectionFactory as well to set the default to false. This ensures the setting correctly propagates to all connections as intended for Jakarta 3.1 compliance.

And will refactor the unit tests to use try-with-resources for better connection management. I will also ensure the embedded broker is explicitly stopped to avoid any flakiness in the CI.

I am working on these changes and will push the updated code shortly

Copy link
Member

@jbonofre jbonofre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR moves Character from the "always valid" set into the "only valid when nested maps enabled".

But Character is not related to maps and lists.

I think modifying nestedMapAndListEnabled is semantically wrong in this context.

I would suggest to create a specific flag for Character, or maybe reject Character if the spec never allowed it.

private long optimizeAcknowledgeTimeOut = 0;
private long optimizedAckScheduledAckInterval = 0;
private boolean nestedMapAndListEnabled = true;
private boolean nestedMapAndListEnabled = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing nestedMapAndListEnabled to false by default is a significant behavioral change that goes well beyond Character rejection.

With false, it means Map and List property values will also be rejected by default. This will break users who rely on the legacy nested map/list support (it's the behavior for years).

I would suggest to not change in the context of this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the guidance. I completely understand your point—changing the nestedMapAndListEnabled default is a very big change and will surely break many legacy users who have been using Maps and Lists for years. I will revert this default back to true.

As suggested, I will introduce a specific flag, complianceMode (or strictCompliance), to handle the Character rejection separately. This way, we can achieve Jakarta 3.1 compliance without affecting the long-standing behavior of Maps and Lists.

I will update the PR with these changes and the refactored tests. Please let me know if this sounds correct to you

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of not having a specific flag just for this. We are just starting working on JMS 3.1 compliance and we may encounter other situations so it may well end up by having many flags.
Having one flag for turning the entire broker into a compatible mode seems relevant to me.
We could as well force (and log of course) nestedMapAndListEnabled to false when the new strictCompliance flag is enabled? Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jeanouii agree, that was basically my proposal.

@pradeep85841
Copy link
Contributor Author

Introduced a strictCompliance flag in ActiveMQConnection and ActiveMQConnectionFactory.

When strictCompliance=true, it automatically forces nestedMapAndListEnabled=false and logs an info message.

Updated ActiveMQMessage to reject Character properties (and other non-standard types) only when strictCompliance is enabled.

Refactored tests to verify the master switch

if (!(value instanceof Map || value instanceof List)) {
throw new MessageFormatException("Only objectified primitive objects, String, Map and List types are allowed but was: " + value + " type: " + value.getClass());
// Standard rules: only primitives and Strings are allowed
if (!(value instanceof Map || value instanceof List || value instanceof Character)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think now that you have the other flag, you can revert the Character part here, what do you think?

Copy link
Contributor

@jeanouii jeanouii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small comment to revert the changes in the other flag if possible

@jeanouii
Copy link
Contributor

@jbonofre I think that looks good now, what do you think?

It's a good compromise, isn't it?


boolean valid = value instanceof Boolean || value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long;
valid = valid || value instanceof Float || value instanceof Double || value instanceof Character || value instanceof String || value == null;
valid = valid || value instanceof Float || value instanceof Double || value instanceof String || value == null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As pointing out by @jeanouii, you are right here to revert the Character change in the validation.

However, as Character is now handled in the connection, the original line works. The strict check should only reject Character when strictCompliance is true.

Maybe it's easier (to read/maintenance) to split in two steps:

  // Keep original line unchanged:
  valid = valid || value instanceof Float || value instanceof Double
      || value instanceof Character || value instanceof String || value == null;

  // Then add strict rejection:
  if (valid && conn != null && conn.isStrictCompliance() && value instanceof Character) {
      throw new MessageFormatException("Character type not allowed under strict Jakarta 3.1 compliance");
  }

@pradeep85841
Copy link
Contributor Author

Reverted the original validation line and added a secondary check to reject Character only when strictCompliance is enabled.

Removed the side-effect where strictCompliance would force nestedMapAndListEnabled to false, preventing inconsistent states as suggested.

Removed the INFO log in the setter and limited flag propagation in the factory to only include the new compliance flag.

Updated the unit tests to verify that strictCompliance correctly enforces Jakarta 3.1 rules even if legacy flags are explicitly enabled.

Copy link
Contributor

@jeanouii jeanouii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
Unless there are hard blockers I'll go ahead and merge later today or tomorrow.

@pradeep85841 Thank you so much for the contributions and your patience.
I appreciate you being very careful about the feedback.

Copy link
Member

@jbonofre jbonofre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latest iteration looks solid and addresses all prior review feedback.

Thanks !

@jeanouii jeanouii merged commit cada078 into apache:main Mar 12, 2026
10 checks passed
@pradeep85841 pradeep85841 deleted the fix/jakarta-31-property-compliance branch March 13, 2026 11:19
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.

3 participants