From d66b268d5db70dfff8a198eefa46834108adbb40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:45:26 +0000 Subject: [PATCH] Docs: Add docs for DS constructor validation Signed-off-by: Christoph Rueger Co-Authored-By: chrisrueger <188422+chrisrueger@users.noreply.github.com> --- docs/_chapters/200-components.md | 104 +++++++++++++++++++++++ docs/_chapters/920-faq.md | 12 +++ docs/_instructions/_ext/dsannotations.md | 6 ++ 3 files changed, 122 insertions(+) diff --git a/docs/_chapters/200-components.md b/docs/_chapters/200-components.md index 2b3de345c7..b32737eb3f 100644 --- a/docs/_chapters/200-components.md +++ b/docs/_chapters/200-components.md @@ -46,6 +46,110 @@ The name of the component is also the implementation class (unless overridden by Annotations are only recognized on the component class, super classes are not inspected for the components. +## Component Class Requirements + +For a class to be a valid DS component, it must meet the following requirements: + +### Constructor Requirements + +A DS component class must have **either**: +- A public no-argument constructor (this is the default constructor if no other constructors are declared), **OR** +- A public constructor annotated with `@Activate` for [constructor injection](https://docs.osgi.org/specification/osgi.cmpn/8.0.0/service.component.html#service.component-constructor.injection) + +If your component class has a constructor with parameters but no `@Activate` annotation, bnd will generate an error: + +``` +The DS component class {className} must declare a public no-arg constructor, or a public constructor annotated with @Activate. +``` + +**Examples of valid components:** + +```java +// Valid: Implicit public no-arg constructor +@Component +public class MyComponent { + // Implicit public no-arg constructor +} + +// Valid: Explicit public no-arg constructor +@Component +public class MyComponent { + public MyComponent() { + // initialization + } +} + +// Valid: Constructor injection with @Activate +@Component +public class MyComponent { + private final BundleContext context; + + @Activate + public MyComponent(BundleContext context) { + this.context = context; + } +} + +// Valid: Multiple constructors with public no-arg +@Component +public class MyComponent { + public MyComponent() { + // default constructor + } + + // This constructor is ignored by DS + public MyComponent(String config) { + // some other constructor + } +} +``` + +**Examples of invalid components:** + +```java +// Invalid: No public no-arg constructor and no @Activate +@Component +public class MyComponent { + public MyComponent(BundleContext context) { + // ERROR: needs @Activate annotation + } +} + +// Invalid: Package-private class (constructor not public) +@Component +class MyComponent { + // ERROR: class must be public +} +``` + +### Inner Class Requirements + +If you use inner classes as components, they **must be declared as `static`**. Non-static inner classes require an instance of the outer class to be instantiated, which DS cannot provide. + +**Valid:** +```java +@Component +public class OuterComponent { + + @Component + public static class InnerComponent { + // Valid: static inner class + } +} +``` + +**Invalid:** +```java +@Component +public class OuterComponent { + + @Component + public class InnerComponent { + // ERROR: non-static inner class cannot be instantiated by DS + } +} +``` + The supported annotations in the `aQute.bnd.annotations.component` package are: ||!Component|| diff --git a/docs/_chapters/920-faq.md b/docs/_chapters/920-faq.md index cd5369d32d..c2afe74a49 100644 --- a/docs/_chapters/920-faq.md +++ b/docs/_chapters/920-faq.md @@ -120,6 +120,18 @@ You can use either file. The reason there are two options is that one constituen ## Why are superclass not inspected for Component annotations? Annotations are not inherited from the component's super classes by default. The problem is that super classes from imported packages may be different at runtime than they were at build time. So it is always best to declare your annotations on the actual component class. Alternatively you can use the instruction `-dsannotations-options: inherit`. Then bnd will use DS annotations found in the class hierarchy of the component class. This will not work for the `@Component` annotation itself; it will not be inherited from super classes causing a subclass to suddenly be a component. +## Why does bnd require a public no-arg constructor for my DS component? +Starting with bnd 7.3.0, bnd enforces the DS specification requirement that component classes must have either a public no-argument constructor or a public constructor annotated with `@Activate` for constructor injection. + +If you see this error: +``` +The DS component class {className} must declare a public no-arg constructor, or a public constructor annotated with @Activate. +``` + +You need to either add a public no-arg constructor, use `@Activate` on your constructor, ensure your class is public, or make inner classes static. + +See [Component Class Requirements](/chapters/200-components.html#component-class-requirements) for detailed explanations and code examples. + ## Can't find the source of the version on an Export-Package? If no explicit export version is specified in the bnd file then bnd will look in the following places. diff --git a/docs/_instructions/_ext/dsannotations.md b/docs/_instructions/_ext/dsannotations.md index 5f1803ce6e..1b7cb18e8d 100644 --- a/docs/_instructions/_ext/dsannotations.md +++ b/docs/_instructions/_ext/dsannotations.md @@ -11,6 +11,12 @@ You provide a comma-separated list of fully qualified class names or use `*` to You can further configure DS annotation processing using the `-dsannotations-options` instruction. +## Component Class Requirements + +When bnd processes DS annotations, it validates that component classes meet the DS specification requirements. Starting with bnd 7.3.0, component classes must have either a public no-argument constructor or a public `@Activate`-annotated constructor. Inner classes must be declared as `static`. + +If validation fails, bnd will generate an error and stop the build. See [Component Class Requirements](/chapters/200-components.html#component-class-requirements) for detailed requirements and examples. + [source](https://github.com/bndtools/bnd/blob/master/biz.aQute.bndlib/src/aQute/bnd/component/DSAnnotations.java)