[ 
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)

Reply via email to