[
https://issues.apache.org/jira/browse/TAP5-2637?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17178964#comment-17178964
]
Dmitry Gusev commented on TAP5-2637:
------------------------------------
For the sake of backwards compatibility and following the [developer bible on
evolving user
interfaces|https://tapestry.apache.org/developer-bible.html#DeveloperBible-UserInterfaces]
we may create `ObjectLocator2` extending `ObjectLocator` and include new
methods there.
Proof of concept and slightly hacky way of implementing the getServices() on
previous tapestry versions:
{code:java}
public interface ObjectLocatorHelper
{
<T> List<T> getServices(Class<T> clazz);
}
public class ObjectLocatorHelperImpl implements ObjectLocatorHelper
{
private final RegistryImpl registryImpl;
private final Method findServiceIdsForInterfaceMethod;
public ObjectLocatorHelperImpl(ObjectLocator objectLocator) throws
NoSuchMethodException, IllegalAccessException
{
if (objectLocator instanceof ServiceBuilderResources || objectLocator
instanceof RegistryWrapper)
{
final Field registryField = getField(objectLocator.getClass(),
"registry", true);
registryImpl = (RegistryImpl) registryField.get(objectLocator);
}
else
{
throw new IllegalArgumentException();
}
// private List<String> findServiceIdsForInterface(Class
serviceInterface)
findServiceIdsForInterfaceMethod =
registryImpl.getClass()
.getDeclaredMethod(
"findServiceIdsForInterface",
Class.class);
findServiceIdsForInterfaceMethod.setAccessible(true);
}
@SuppressWarnings("unchecked")
@Override
public <T> List<T> getServices(Class<T> clazz)
{
try
{
final List<String> serviceIds =
(List<String>)
findServiceIdsForInterfaceMethod.invoke(registryImpl, clazz);
if (serviceIds == null || serviceIds.isEmpty())
{
return List.of();
}
return serviceIds
.stream()
.map(serviceId -> registryImpl.getService(serviceId, clazz))
.collect(toList());
}
catch (IllegalAccessException | InvocationTargetException e)
{
throw new RuntimeException(e);
}
}
}
{code}
> Provide API to query multiple/all service instances from ObjectLocator by
> service interface/markers
> ---------------------------------------------------------------------------------------------------
>
> Key: TAP5-2637
> URL: https://issues.apache.org/jira/browse/TAP5-2637
> Project: Tapestry 5
> Issue Type: Improvement
> Components: tapestry-ioc
> Reporter: Dmitry Gusev
> Priority: Major
>
> Tapestry IoC's `ObjectLocator` can only return a service if there's exactly
> one implementation matching criteria:
>
> {code:java}
> <T> T getService(Class<T> serviceInterface)
> <T> T getService(Class<T> serviceInterface, Class<? extends Annotation>...
> markerTypes);
> {code}
> It's sometimes necessary to get all registered services, i.e. when
> integrating with 3rd party libraries that support "bring your own service
> discovery", they expect this functionality from service discovery.
> At present `RegistryImpl` has everything we need to implement this feature,
> see `#findServiceIdsForInterface` and `#findServiceDefsMatchingMarkerAndType`.
>
> As future work we could also support list-type injections, i.e.
> {code:java}
> @Inject List<ServiceA> multipleInjections;{code}
> Marker annotations would fit nicely here, e.g. `@Inject @Blue List<ServiceA>
> multipleInjections;`
> In theory it may break injections for services that implement the `List`
> interface itself, unsure if there are any real use-cases for it. But as all
> service definitions are known upfront on registry initialisation we may
> implement a safety check and fail with error if there's any. We may also
> provide a symbol to disable List-injections, and only run the mentioned
> check/failure if the symbol is enabled.
>
--
This message was sent by Atlassian Jira
(v8.3.4#803005)