We had custom implementation of ResourceProvider based on org.apache.sling.api.resource.ResourceProvider API. It was working fine with AEM6.1.
After migration to AEM6.4, we had few issues with this implementation-
1. Authoring was not working for all pages under root paths. For example- /content/mysite/products and /content/yoursite/products
2. In publishers, under these paths sling:alias functionality does not work.
Because this implementation was based on deprecated API, Adobe suggested us to re-write this implementation using new API- org.apache.sling.spi.resource.provider.ResourceProvider.
But, this new implementation is unstable and the containing bundle does not get installed while deployment. It keeps on installing this bundles for long duration and system gets unstable.
Below is old implementation-
@Service
@Component(immediate = true, metatype = true, policy = ConfigurationPolicy.REQUIRE)
@Properties({ @Property(name = ResourceProvider.ROOTS, value = { "/content/mysite/products", "/content/yoursite/products" }) })
public class CustomResourceProvider implements ResourceProvider {
private static final Logger LOG = LoggerFactory.getLogger(CustomResourceProvider.class);
@Override
@Deprecated
public Resource getResource(ResourceResolver resourceResolver, HttpServletRequest request, String path)
{
return null;
}
@Override
public Resource getResource(ResourceResolver resolver, String path)
{
// method to return resource
}
@Override
public Iterator<Resource> listChildren(Resource arg0)
{
return null;
}
}
Below is new implementation-
@Service(ResourceProvider.class)
@Component
@Properties({
@Property(name = ResourceProvider.PROPERTY_ROOT, value = { "/content/mysite/products", "/content/yoursite/products" }) ,
@Property(name = ResourceProvider.PROPERTY_ADAPTABLE, boolValue = true),
@Property(name = ResourceProvider.PROPERTY_ATTRIBUTABLE, boolValue = true),
@Property(name = ResourceProvider.PROPERTY_MODIFIABLE, boolValue = true),
@Property(name = ResourceProvider.PROPERTY_REFRESHABLE, boolValue = true),
@Property(name = ResourceProvider.PROPERTY_AUTHENTICATE, value = ResourceProvider.AUTHENTICATE_REQUIRED)
})
public class CustomResourceProvider extends ResourceProvider<Object> {
private static final Logger LOG = LoggerFactory.getLogger(CustomResourceProvider.class);
/** The resource resolver factory. */
@Reference
private ResourceResolverFactory resourceResolverFactory;
@Reference(target = "(provider.root=/)")
private volatile ResourceProvider<Object> rp;
@Override
public Resource getResource(ResolveContext<Object> ctx, String path, ResourceContext resourceContext, Resource parent)
{
Resource productResource = getProductResource(ctx, path, resourceContext, parent);
return productResource != null ? productResource : rp.getResource(ctx, path, resourceContext, parent);
}
public Resource getProductResource(ResolveContext<Object> ctx, String path, ResourceContext resourceContext, Resource parent)
{
// method to return resource
}
@Override
public Iterator<Resource> listChildren(ResolveContext<Object> paramResolveContext, Resource paramResource)
{
return rp.listChildren(paramResolveContext, paramResource);
}
public Object authenticate(Map<String, Object> authenticationInfo) throws LoginException
{
return rp.authenticate(authenticationInfo);
}
public void logout(Object state)
{
rp.logout(state);
}
public void refresh(ResolveContext<Object> ctx)
{
rp.refresh(ctx);
}
public boolean isLive(ResolveContext<Object> ctx)
{
return rp.isLive(ctx);
}
public Resource getParent(ResolveContext<Object> ctx, Resource child)
{
return rp.getParent(ctx, child);
}
public Collection<String> getAttributeNames(ResolveContext<Object> ctx)
{
return rp.getAttributeNames(ctx);
}
public Object getAttribute(ResolveContext<Object> ctx, String name)
{
return rp.getAttribute(ctx, name);
}
public Resource create(ResolveContext<Object> ctx, String path, Map<String, Object> properties) throws PersistenceException
{
return rp.create(ctx, path, properties);
}
public void delete(ResolveContext<Object> ctx, Resource resource) throws PersistenceException
{
rp.delete(ctx, resource);
}
public void revert(ResolveContext<Object> ctx)
{
rp.revert(ctx);
}
public void commit(ResolveContext<Object> ctx) throws PersistenceException
{
rp.commit(ctx);
}
public boolean hasChanges(ResolveContext<Object> ctx)
{
return rp.hasChanges(ctx);
}
public QueryLanguageProvider<Object> getQueryLanguageProvider()
{
return rp.getQueryLanguageProvider();
}
public <AdapterType> AdapterType adaptTo(ResolveContext<Object> ctx, Class<AdapterType> type)
{
return rp.adaptTo(ctx, type);
}
public boolean copy(ResolveContext<Object> ctx, String srcAbsPath, String destAbsPath) throws PersistenceException
{
return rp.copy(ctx, srcAbsPath, destAbsPath);
}
public boolean move(ResolveContext<Object> ctx, String srcAbsPath, String destAbsPath) throws PersistenceException
{
return rp.move(ctx, srcAbsPath, destAbsPath);
}
}
Solved! Go to Solution.
Views
Replies
Total Likes
Hi,
That's not really AEM specific and I doubt that you find a lot of people here who have created a ResourceProvider on their own. I would suggest that you reach out to the Apache Sling User mailing list [1] and ask there for public. I would recommend you to be a bit more specific regarding the stability issue you face. With the above problem description it's hard to give any recommendation what you should change to improve your implementation.
Views
Replies
Total Likes
Hi,
That's not really AEM specific and I doubt that you find a lot of people here who have created a ResourceProvider on their own. I would suggest that you reach out to the Apache Sling User mailing list [1] and ask there for public. I would recommend you to be a bit more specific regarding the stability issue you face. With the above problem description it's hard to give any recommendation what you should change to improve your implementation.
Views
Replies
Total Likes
Also - I would look at using R6 annotations and moving off Felix SRC annotations.
Views
Replies
Total Likes