---
order: 235
title: Accessor Properties
layout: default
---

When working with _custom bundle annotations_ one may find that `@Attribute` and `@Directive` have limitations in scenarios where multiple _bundle annotations_ are added to a single _custom bundle annotation_ because there are no discriminators expressing which _bundle annotation_ to associate the attribute or directive; and it's likely that associating these with all _bundle annotations_ produces unexpected or even incorrect results. Bnd provides a solution which takes advantage of its macro support during annotation processing.

## Accessor Properties

When an annotation is meta-annotated with a _bundle annotation_ the values and defaults of the host are loaded as properties, prefixed with `#`, into the macro processing scope. The effect is that these values are accessible using a [macro pattern](/chapters/850-macros.html#macro-patterns) (like `${}`).

```java
@Capability(
    name = "${#name}", // <-- accesses the hosts 'name()' value
    namespace = "osgi.cdi.extension",
    version = "${#version}"  // <-- accesses the hosts 'version()' value
)
@Requirement(
    name = "osgi.cdi",
    namespace = "osgi.implementation",
    version = "1.0.0")
@interface CDIExtension {
    String name();
    String version();
}
```

Annotation methods may return several different types and they are converted to strings according to the following table:

| Return type                      | Conversion |
| :----------                      | :------- |
|`boolean`, `byte`, `char`, `double`, `float`, `int`, `long`, `short`|`String.valueOf()`|
|`java.lang.Class`                 |`Class.getName()`|
|`java.lang.Enum`                  |`Enum.name()`|
|`java.lang.String`                |_as is (commas should be escaped with `\`)_|
|array type whose component type is one of the preceding types|_joined by comma (`,`)_|
|type satisfying `Class.isAnnotation()`|_omitted from available accessor properties_|
|array type whose component type satisfies `Class.isAnnotation()`|_omitted from available accessor properties_|

**It should be noted** that if the resulting strings contain *macro characters* these will be interpreted by bnd's macro engine. This may produce unexpected results due to potentially nested macros. In this scenario steps must be taken to either escape these characters or that nesting is done to allow bnd to successfully process the result.

#### The annotated type as default

The return type `Class<?>` is particularly useful when it comes to making your code friendly to refactoring.

```java
@Capability(
    filter = "objectClass:List<String>='${#value}'",
    namespace = "osgi.service",
)
@interface MyService {
    Class<?>[] value();
}

// applied as

@MyService(Bar.class)
class Bar { ... }
```

What if you want the default to be _the annotated class_ itself? Bnd made this possible by using a type which was unlikely to be a real argument. The type selected was `java.lang.annotation.Target`because it is guaranteed to be accessible, is unlikely to be a real argument, will not require an additional dependency, and it's nomenclature proved the most expressive for the use case.

```java
@Capability(
    filter = "objectClass:List<String>='${#value}'",
    namespace = "osgi.service",
)
@interface MyService {
    Class<?>[] value() default Target.class;
}

// applied as

@MyService
class Bar { ... }
```

Instances of `java.lang.annotation.Target.class` found in the return value of `Class<?>` or `Class<?>[]` methods will be replaced by the annotated type prior to string conversion.

#### Cardinality

In order to control the cardinality of requirements generated by *custom bundle annotations* a convenience enum `aQute.bnd.annotation.Cardinality` is available as a method return type. The default value should be `Cardinality.DEFAULT` ensuring that if not set no directive will be emitted.

```java
@Requirement(
    attribute = {
        aQute.bnd.annotation.Constants.CARDINALITY_MACRO
    },
    namespace = "osgi.service",
)
@interface RequireMyService {
    Cardinality cardinality() default Cardinality.DEFAULT;
}

// applied as

@RequireMyService(cardinality = Cardinality.MULTIPLE)
class Bar { ... }
```

**Note:** It is recommended to use the macro constant `aQute.bnd.annotation.Constants.CARDINALITY_MACRO` crafted specifically for handling the cardinality directive. It should also be noted that during macro processing the enum `name()` will be converted to lower case.

#### Resolution

In order to control the resolution of requirements generated by *custom bundle annotations* a convenience enum `aQute.bnd.annotation.Resolution` is available as method return type. The default value should be `Resolution.DEFAULT` ensuring that if not set no directive will be emitted.

```java
@Requirement(
    attribute = {
        aQute.bnd.annotation.Constants.RESOLUTION_MACRO
    },
    namespace = "osgi.service",
)
@interface RequireMyService {
    Resolution resolution() default Resolution.DEFAULT;
}

// applied as

@RequireMyService(resolution = Resolution.OPTIONAL)
class Bar { ... }
```

**Note:** It is recommended to use the macro constant `aQute.bnd.annotation.Constants.RESOLUTION_MACRO` crafted specifically for handling the resolution directive. It should also be noted that during macro processing the enum `name()` will be converted to lower case.

#### Effective

In order to control the effective time of a requirement generated by *custom bundle annotations* a method called `effective` with a return type of `String` can be used in conjunction with the macro constant `aQute.bnd.annotation.Constants.EFFECTIVE_MACRO`. The default value should be the empty string (`""`) ensuring that if not set no directive will be emitted.

```java
@Requirement(
    attribute = {
        aQute.bnd.annotation.Constants.EFFECTIVE_MACRO
    },
    namespace = "osgi.service",
)
@interface RequireMyService {
    String effective() default "";
}

// applied as

@RequireMyService(effective = "active")
class Bar { ... }
```

#### Uses

In order to control the uses constraints of a requirement generated by *custom bundle annotations* a method called `uses` with a return type of `Class<?>[]` can be used in conjunction with the macro constant `aQute.bnd.annotation.Constants.USES_MACRO`. The default value should be an empty array (`{}`) ensuring that if not set the directive will not be emitted.

```java
@Requirement(
    attribute = {
        aQute.bnd.annotation.Constants.USES_MACRO
    },
    namespace = "osgi.service",
)
@interface RequireMyService {
    Class<?>[] uses() default {};
}

// applied as

@RequireMyService(uses = {com.acme.Foo.class, org.bar.Bar.class})
class Bar { ... }
```





#### 
