To David,

Your comment got me thinking some more about this. And given that I have
about 25 different variations and each has 3 variants, that would mean
introducing somewhere like 75 "marker" interfaces.

Here's what I did:

A number of key classes are generated and sometimes partly modified by
hand. So in the "main" such class I have:
/**
 * This class is generated by Iris-Mapping.
 *
 * @generated
 */
@Component(
    property = {
        IBaseMapData.CONFIG_MAPPING_ID + "=" +
"com.castortech.iris.mapping.project.baModel.asset",
        IBaseMapData.CONFIG_MAPPING_NAME + "=" +
BaModelAssetMapData.TABLE_NAME,
        IBaseMapData.CONFIG_MAPPING_XL_READER + "=" +
"com.castortech.iris.mapping.maps.project.baModel.asset.BaModelAssetXlReader",
        IBaseMapData.CONFIG_MAPPING_XL_WRITER + "=" +
"com.castortech.iris.mapping.maps.project.baModel.asset.BaModelAssetXlWriter"
    },
    service=BaModelAssetMapData.class
)
public final class BaModelAssetMapData extends
BaseMapData<BaModelAssetMapTable, BaModelAssetMapRecord> {
  public static final String TABLE_NAME = "Asset"; //$NON-NLS-1$
  public static final String PROP_TABLE_NAME =
MappingConstants.CONFIG_TABLE_NAME + "=" + TABLE_NAME; //$NON-NLS-1$
  public static final String TARGET_TABLE_NAME = "(" +
MappingConstants.CONFIG_TABLE_NAME + "=" + TABLE_NAME + ")"; //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$
...

and then I will have:
@Component(property=BaModelAssetMapData.PROP_TABLE_NAME)
public final class AssetXlExporter implements BaXlExportContent {
    @Reference
    private BaXlExportUtils<BaModelAssetXlWriter, BaModelAssetMapTable,
BaModelAssetMapRecord> exporter;

    @Reference(target=BaModelAssetMapData.TARGET_TABLE_NAME)
    private ExportTable<BaModelAssetMapTable> exportTable;

and in another location where the exporter is used as a reference:
    ....
    @Reference(target=BaModelAssetMapData.TARGET_TABLE_NAME)
    private AssetXlExporter assetXlExporter;
    ...

To me this avoids the previous issue of exposing the implementation class
and using generated constants, allows to have readable code where
annotations don't become unreadable.

Does it make sense?

Alain

On Sun, Aug 12, 2018 at 8:22 AM David Leangen <o...@leangen.net> wrote:

>
> Hi Alain,
>
> Maybe there is a way of having 25 different interfaces in your API instead?
>
> Or, if they are private, maybe you don’t even need to use services?
>
> Are you able to share your code? Would be helpful to have a little more
> information.
>
>
> Cheers,
> =David
>
>
>
> On Aug 12, 2018, at 6:58, Alain Picard <pic...@castortech.com> wrote:
>
> On Sat, Aug 11, 2018 at 4:10 PM David Leangen <o...@leangen.net> wrote:
>
>>
>> Hi Alain,
>>
>> What is it you are trying to accomplish? Is there a reason you are
>> exposing the implementation class?
>>
>> Maybe you know this already, but the “usual” practice is to expose an
>> interface in your API (and export the containing package), and to keep the
>> implementation private.
>>
> Yes, absolutely, and that's why I'm asking. I have about 25 different
> implementation of the interfaces that are most often referenced directly
> from a matching component (i.e. for the same table) and a few cases where
> they are invoked generically. Here all of those are in a single bundle so
> this is more like a "private" API and the use of a class is not a real
> problem. But I didn't feel like using @Reference(target=(tableName=x) for
> each case. Hence my question.
>
> Alain
>
>>
>> Also:
>>
>> >                Collection<ServiceReference<T>> servRefs =
>> bcontext.getServiceReferences(target, props.get("filter"));  //filter to be
>> like: "(target
>> >         servRef = servRefs.isEmpty() ? null :
>> servRefs.iterator().next();
>>
>> Did some text get cut out of your post?
>>
>> If you can explain a little more what you are trying to do I think that
>> would be helpful.
>>
>>
>> Cheers,
>> =David
>>
>>
>> > On Aug 12, 2018, at 1:27, Alain Picard via osgi-dev <
>> osgi-dev@mail.osgi.org> wrote:
>> >
>> > Looking for confirmation or insight in how best to specify components
>> and references, so that the same component can be invoked directly or more
>> generically through its interface.
>> >
>> > Let's say that I have some components, 1 per table to do some export
>> function:
>> >
>> > @Component(
>> >         property= MappingConstants.CONFIG_TABLE_NAME + "=BigTable",
>> >         service= { BigTableXlExporter.class, XlExportContent.class }
>> > )
>> > public final class BigTableXlExporter implements XlExportContent {...}
>> >
>> > and in another component I can get a specific reference with:
>> > @Component(service=SomeComp.class)
>> > public final class SomeComp
>> >     @Reference
>> >     private BigTableXlExporter exporter;
>> >     ...
>> > }
>> >
>> > and in another case i could get a more generic invocation (as part of
>> config or through a factory:
>> > @Component(service=GenericComp.class)
>> > public final class GenericComp
>> >    @Activate
>> >    private void init(Map<String,Object> props, BundleContext bcontext) {
>> >      ServiceReference servRef;
>> >       try {
>> >          Collection<ServiceReference<T>> servRefs =
>> bcontext.getServiceReferences(target, props.get("filter"));  //filter to be
>> like: "(target
>> >         servRef = servRefs.isEmpty() ? null :
>> servRefs.iterator().next();
>> >         }
>> >         catch (InvalidSyntaxException e) {
>> >             throw new IllegalArgumentException("Invalid Filter Syntax
>> Exception", e);
>> >         }
>> >
>> >         //do something with ref....
>> >    }
>> > }
>> >
>> > Does this make sense or are there better ways to do this.
>> >
>> > Alain
>> >
>> > _______________________________________________
>> > OSGi Developer Mail List
>> > osgi-dev@mail.osgi.org
>> > https://mail.osgi.org/mailman/listinfo/osgi-dev
>>
>>
>
_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to