Here is my code:
- An interface :
public interface FieldProvisioner {
Optional<FieldProvisionRecord> provisionField(FieldProvisionRecord record);
FieldName getFieldName();
}
- An abstract Base Class that implements the above interface
`
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.ServiceException;
import org.osgi.service.log.LogService;
@Properties({
@Property(name=FieldProvisionerServiceBase.PROP_TCH, boolValue=false)
})
@Component
@Service
public abstract class FieldProvisionerServiceBase implements FieldProvisioner {
public static final String PROP_TCH = "tch";
@Reference
protected LogService logger;
protected Boolean tch = false;
@Activate
public void activate(final Map<String, Object> properties) {
OsgiServiceValueHelper helper = new OsgiServiceValueHelper(properties);
tch = helper.getBoolean(PROP_TCH).orElse(false);
}
@Override
public Optional<FieldProvisionRecord> provisionField(final FieldProvisionRecord record,
final Consumer<Exception> onError) {
//some implementation
}
}
- Multiple classes like the one below (Soccer, Cricket, etc.) who extend the above abstract class
@Service
@Component
public class CricketProvisionerServiceImpl extends FieldProvisionerServiceBase {
String FACTORY_NAME = "some.osgi.server.fieldprovision.CricketProvisionerServiceImpl";
String FACTORY_FILTER = "(component.factory="+FACTORY_NAME+")";
@Override
public String getFactoryFilter() {
return FACTORY_FILTER;
}
@Reference(target="(component.factory=\"tch.server.fieldprovision.CricketProvisionerServiceImpl\")")
ComponentFactory fieldProvisionerFactory;
@Override
public FieldName getFieldName() {
return FieldName.CRICKET;
}
}
Now I have a Factory which gives me the class instance I need when I call it.
@Service
@Component
@References({
@Reference(name="fieldProvisioners",
bind="addService", unbind="removeService",
referenceInterface=FieldProvisioner.class,
cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE, policy=ReferencePolicy.DYNAMIC)
})
public class FieldProvisionerFactoryImpl implements FieldProvisionerFactory {
private List<FieldProvisioner> services = new CopyOnWriteArrayList<>();
@Override
public Optional<FieldProvisioner> getProvisionerService(final FieldName name) {
Optional<FieldProvisioner> provisioner = services
.stream()
.filter(service -> service.getFieldName().equals(fieldDefinition.name))
.findFirst();
if (!provisioner.isPresent()) {
//do something
}
return provisioner;
}
protected void addService(final FieldProvisioner check,
final Map<String, Object> properties) {
this.services.add(check);
}
protected void removeService(final FieldProvisioner check,
final Map<String, Object> properties) {
this.services.remove(check);
}
}
The problem is every time I call FieldProvisionerFactory's getProvisionerService (with field name CRICKET), I expect a different instance of the service (CricketProvisionerServiceImpl). However, I get the same instance.
I am using older version of declarative services (with felix scr annotation - 1.9.12) which doesn't support the ReferenceScope. So I am trying to use componentFactory to get a different instance everytime a consumer calls.
Any thoughts on how to do it , any pointers, help?