Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

Caching per path

SInce Slice 4.1 you can cache your SliceResources created for a given path within single request processing.This is especially helpful if you have a heavy object (which reads a lot of properties) and you are using it a couple of times within single request, e.g. PageModel which keeps your page properties - this model may be often referenced by other components and there's no need to re-create it each time. Please note that caching can only be applied for resources which are not changed while a request is processed, otherwise such changes won't be reflected in cached objects.

Additionally, caching works not only within request context but also in osgi-services context. It's basically based on Slice's @ContextScope.

To make your SliceResources cacheable per path you should simply annotate them with @Cacheable annotation.

@SliceResource
@Cacheable
public class PageModel {
	@JcrProperty("jcr:title")
	private String title;
	...
} 

Simpler OSGi service support

If you want to use OSGi services within your guicified code, you can simple go for Peaberry solution which allows you to bind an interface to OSGi service (Slice is shipped with Peaberry out of the box). Normally, you bind OSGi services in some Guice module, e.g.

public class MyAppModule extends AbstractModule {
	@Override
	public void configure() {
		bind(ResourceResolverFactory.class).toProvider(Peaberry.service(ResourceResolverFactory.class)).single());
		// other bindings
	}
}

public class MyClass {
	@Inject
	ResourceResolverFactory factory;
    ...
}

From now on, you can simplify this declarations and Slice will do the work for you. You just need to annotate field or constructor argument with @OsgiService and Slice will bind such an interface/class to a Peaberry provider, making it injectable. So your code can just look like this:

public class MyClass {
	@Inject
	@OsgiService
	ResourceResolverFactory factory;
    ...
}

Injector registration

Injector listener

Sometimes it's necessary to use Slice bindings during the activation of the OSGi component. It can't be done in the @Activate method, as there is a race between component activation and the application activator that creates Slice injector - the result is that Slice injector isn't created yet, so OSGi component can't use it. The workaround is to use lazy loading and initialize data on the first request, but it may make the OSGi service design more complex.

The new InjectorListener interface allows to overcome this problem. It contains method injectorAvailable(String) that will be invoked for each injector that has been already created. Therefore, the initialization logic may be moved there:

@Component
@Service
public class MyComponent implements InjectorListener {
	// we need to have this atomic boolean, as the injector may become available
	// a few times during component lifecycle
	private final AtomicBoolean initialized = new AtomicBoolean();

	@Activate
	protected void activate() {
		initialized.set(false);
	}

	@Override
	public void injectorAvailable(String injectorName) {
		if ("myapp".equals(injectorName) && !initialized.getAndSet()) {
			InjectorWithContext injector = InjectorUtil.getInjector("myapp", getResolver());
			// do something clever with the injector
		}
	}
}
  • No labels