Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions docs/_chapters/200-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -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||
Expand Down
12 changes: 12 additions & 0 deletions docs/_chapters/920-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -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? <a name="supercomps"/>
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? <a name="componentConstructor"/>
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? <a name="exportversions"/>
If no explicit export version is specified in the bnd file then bnd will look in the following places.

Expand Down
6 changes: 6 additions & 0 deletions docs/_instructions/_ext/dsannotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

<hr />
Expand Down
Loading