You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by "Dmitry Gusev (Jira)" <ji...@apache.org> on 2020/08/17 13:01:00 UTC
[jira] [Commented] (TAP5-2637) Provide API to query multiple/all
service instances from ObjectLocator by service interface/markers
[ 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)