Skip to content

Conversation

@headius
Copy link
Member

@headius headius commented Oct 8, 2025

Working on some demo applications for a JRuby Spring Boot meta-framework, I've had to deal with some challenges and inconsistencies in how annotations are applied. This PR aims to address those so simplify annotation-heavy use of JRuby's class reification subsystem.

See https://github.com/headius/boing for some of these examples.

  • Allow symbols for keys in annotation maps

This allows doing annotations like:

add_class_annotations(Entity => {name: "Employee"})

and similar for methods and parameters.

  • Modify boot sequence to delay requires until after initialization.
  • Modify boot sequence to avoid registering global runtime unless explicit.
  • Improve naming and usability, with single-class forms and better use of Ruby 3.4 syntax)
  • Test updates and additions

@headius
Copy link
Member Author

headius commented Oct 8, 2025

See headius/boing#2 for related work on the other side (the new "boing" library).

@headius headius changed the title Improvements to annotation processing Improvements for annotation framework use Oct 8, 2025
This allows doing annotations like:

```
add_class_annotations(Entity => {name: "Employee"})
```

and similar for methods and parameters.
This change primarily moves the loading of command-line requires
further into the "main" execution path, rather then running them
on instantiation of Ruby before other state has been set up.

When the command-line requires depend on other state set up by the
main path, it may behave differently to require at the command line
versus requiring in the first executed file. One example is that
no thread context classloader will be set when these files run.

Such a case was found working on a Spring Boot application. When
the Spring classes were loaded and registered before the main
script started, they would have a misconfigured SLF4J logger and
fail to boot. Moving that logic into the main script fixed the
issue, presumably because the early stages of Spring Boot's boot
process depends on the context classloader.

This moves the automatic load of command-line required files to
the main path in the method `runFromMain`. A new `boot` method is
added to include these pre-execution startup items.

A new constructor method `newMain` is added for the main path to
create a new runtime without immediately booting it, allowing for
that to happen during main execution. The other forms of
`newInstance` are modified to pre-boot the runtime, assuming it
will immediately be used to execute code.
@headius headius force-pushed the symbols_for_annotation_keys branch from 94090c9 to 0ea455e Compare October 8, 2025 21:27
The default behavior to create a new runtime would check if a
global runtime had been intialized, and if not it called the
newInstance method expecting that the result would be registered as
the global runtime. With the changes in this PR we no longer do
this automatic registration, so the code here is changed to use
getGlobalRuntime methods that explicitly create and register the
runtime.

This exposes a risk in changing the global registration lifecycle
for the newInstance methods: any code that expects the simple act
of calling newInstance to register a global runtime will need to
be updated to avoid that expectation, either capturing the runtime
returned or calling getGlobalRuntime or useAsGlobalRuntime to
ensure that the new runtime instance is registered. I don't expect
there to be a lot of code calling these APIs directly.
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.

1 participant