Expand my Community achievements bar.

SOLVED

AEM 6.3: ResourceProvider, session closed

Avatar

Level 5

I have a class (extending 'ResourceProvider) that returns the properties of a configuration file. Here is my code:

@Override

public Resource getResource(ResolveContext resolveContext, String path, ResourceContext resourceContext, Resource resource) {

    try {

        resolver = resourceResolverFactory.getServiceResourceResolver(AutoClosableResourceResolverFactory.getCredentials());

        LOG.info("[ConfigResourceProvider]: initialized resolver");

        String configPath = getLiveCopyConfigPath(path);

        Resource configResource = resolver.getResource(configPath);

        if (configResource != null && !configResource.isResourceType(Resource.RESOURCE_TYPE_NON_EXISTING)) {

            ValueMap vm = configResource.getValueMap();

            return new ConfigResource(resolver, path, vm);

        }

    } catch (LoginException e) {

        LOG.error("A problem occurred when logging in, into the repository", e);

        LOG.error(ExceptionUtils.getStackTrace(e));

    } finally {

        if (resolver != null) {

            resolver.close();

            LOG.info("[ConfigResourceProvider]: closed resolver");

        }

    }

    return null;

}

As you can see I close my resolver in the finally block to avoid blocked session and other related issues. Later on in the code I use this resource and its valueMap in an adaptTo method but this triggers an exception:

Caused by: java.lang.IllegalArgumentException: javax.jcr.RepositoryException: This session has been closed.

at org.apache.sling.jcr.resource.internal.JcrValueMap.readFully(JcrValueMap.java:395)

at org.apache.sling.jcr.resource.internal.JcrValueMap.size(JcrValueMap.java:174)

at java.util.HashMap.putMapEntries(HashMap.java:500)

at java.util.HashMap.putAll(HashMap.java:784)

at com.company.core.provider.GeneralResource.createValueMap(GeneralResource.java:39)

at com.company.core.provider.GeneralResource.adaptTo(GeneralResource.java:24)

at org.apache.sling.api.resource.AbstractResource.getValueMap(AbstractResource.java:136)

at com.company.config.LiveCopyConfigAdapter.adaptResourceToLiveCopyConfig(LiveCopyConfigAdapter.java:15)

at com.company.config.LiveCopyConfigAdapterFactory.getAdapter(LiveCopyConfigAdapterFactory.java:37)

at org.apache.sling.adapter.internal.AdapterManagerImpl.getAdapter(AdapterManagerImpl.java:147)

at org.apache.sling.api.adapter.SlingAdaptable.adaptTo(SlingAdaptable.java:104)

at com.company.core.provider.GeneralResource.adaptTo(GeneralResource.java:28)

at com.company.config.ConfigService.getLiveCopyConfig(ConfigService.java:25)

... 173 common frames omitted

Caused by: javax.jcr.RepositoryException: This session has been closed.

at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.checkAlive(SessionDelegate.java:324)

at org.apache.jackrabbit.oak.jcr.delegate.ItemDelegate.checkAlive(ItemDelegate.java:83)

at org.apache.jackrabbit.oak.jcr.session.operation.ItemOperation.checkPreconditions(ItemOperation.java:34)

at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.prePerform(SessionDelegate.java:615)

at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.perform(SessionDelegate.java:205)

at org.apache.jackrabbit.oak.jcr.session.ItemImpl.perform(ItemImpl.java:112)

at org.apache.jackrabbit.oak.jcr.session.NodeImpl.getProperties(NodeImpl.java:645)

at org.apache.sling.jcr.resource.internal.JcrValueMap.readFully(JcrValueMap.java:388)

How can I prevent this from happening? Thanks in advance!

1 Accepted Solution

Avatar

Correct answer by
Level 5

I fixed it by passing a copy of the ValueMap into my synthetic resource:

return new ConfigResource(resolver, path, new ConfigResource.ConfigValueMap(vm));

static class ConfigValueMap extends ValueMapDecorator {

    ConfigValueMap(final Map<String, Object> valueMap) {

        super(new HashMap<>());

        putAll(valueMap);

    }

}

View solution in original post

1 Reply

Avatar

Correct answer by
Level 5

I fixed it by passing a copy of the ValueMap into my synthetic resource:

return new ConfigResource(resolver, path, new ConfigResource.ConfigValueMap(vm));

static class ConfigValueMap extends ValueMapDecorator {

    ConfigValueMap(final Map<String, Object> valueMap) {

        super(new HashMap<>());

        putAll(valueMap);

    }

}