Symfony2 dependency Injection : performances impact - performance

I'm refactoring one of my controller to make it a service and I want to know if there is a performance impact to not inject whole service container into my controller.
Is this is more efficient :
innova.path.controller:
class: %innova.controller.path.class%
arguments:
entityManager: #doctrine.orm.entity_manager
session: #session
securityContext: #security.context
router: #router
translator: #translator
pathManager: #innova.manager.path_manager
calls:
- [setRequest, ["#?request="]]
scope: request
than this, for example ?
innova.path.controller:
class: %innova.controller.path.class%
arguments: [#service_container]

Official documentation explicitly tell to not inject whole DIC into a Controller (thanks #NHG for link).
Section How to work with scopes :
Injecting the whole container into a service is generally not a good
idea (only inject what you need).
But in section Service container :
When you ask for the my_mailer service from the container, the
container constructs the object and returns it. This is another major
advantage of using the service container. Namely, a service is never
constructed until it's needed. If you define a service and never use
it on a request, the service is never created. This saves memory and
increases the speed of your application. This also means that there's
very little or no performance hit for defining lots of services.
Services that are never used are never constructed.
So injecting the whole DIC to controller will not have performances impact because only the services used in controller are instanciated.

The idea of using controllers as service is injecting only necessery services. Standard controller extends Symfony\Bundle\FrameworkBundle\Controller\Controller which extending Symfony\Component\DependencyInjection\ContainerAware. So, injecting whole container is makes no sense...
Generally, injecting less service is more efficient than injecting whole container.
Additionally you should familiarize with base Symfony2 Controller class.

Related

Are services in AEM really singleton?

I have an interface which I have implemented. I have annoted the impl with #Component and #Service of the package org.apache.felix.scr.annotations.
I wrote a simple constructor for my impl
public MyImpl(){
LOG.info("New instance created!!");
}
I also added loggers in #activate and #deactivate method.
I expected to see "New instance created!!" only once BUT I can see activate and deactivate method being called per request I make on a page(This service is invoked by A Sling Model which is used in that page)
What I saw was "New instance created!!" logged several times.
This means the OSGi container create multiple instances of my Service and called the activate and deactivate method every time.
This shows that this is not a Singleton.
The Object should be discarded only when I uninstall my bundle.
Please help me understand what is going on here.
I WANT TO IMPLEMENT A TRUE SINGLETON IN AEM
I have implemented this in AEM 6.5 instance which uses Apache Felix.
Edit:
Adding Service properties:
aemRootUrl http://localhost:8080
api.http.connections_manager.timeout 60000
api.http.cookie_max.age 18000
api.http.max_connections 200
api.http.max_connections_per_host 20
api.http.timeout.connection 300000
api.http.timeout.socket 300000
api.server.ssl.trust_all_certs true
api.server.url https://10asdasdsad
api.server.username admin
component.id 3925
component.name com.example.foundation.core.connection.impl.HybrisConnectionImpl
non_akamai.api.server.url hadasdadasd
service.bundleid 585
Service PID com.example.foundation.core.connection.impl.HybrisConnectionImpl
service.scope bundle
Using Bundles com.example.dumb-foundation.core (585)
Values altered to hide client specific information
EDIT::
I've removed the SCR annotations and replaced them with OSGI annotations here I've explictly specified
#Component(service =HybrisConnection.class, immediate=true,scope = ServiceScope.SINGLETON)
But still is shows as scope=bundle.
Should I enforce Singleton and OSGi annotations on it's dependencies as well for this to be a proper Singleton?
In declarative services (which is what you use behind the scenes) there are some cases when a component (and its service) is unpublished.
By default a simple component with immediate=true will come up when the bundle starts and go down when it stops.
If your component has any mandatory service dependencies (#Reference) then it will only be active while all dependencies are present. So if at least one dependent service goes away the component will be deactivated.
In addition the component might get restarted when config is not present at start but added later. If you want to avoid this make the config required.
Every thing #Christian Schneider said is true.
They AEM services are Singletons but are deactivated/unpublished at times. This might be for various reasons.
I faced a horrible issue because of ConfigurationAdmin service. Using this services caused our OSGi config files to be bound to the wrong bundle i.e. SlingModels. bundle within AEM.
the only way to access this is by getting the service using configAdmin.getConfig(PID).setBundleLocation(null);
BUT Doing this causes the service that is linked to this configuration to restart.
So every time I did config.setBundleLocation(null) the service restarted.
The best and most awesome way to resolve this is use OCD to define configuration for OSGi Services linked to OSGi config.xmls
AND NEVER EVER EVER use configuration Admin
If you want to access properties of another service Say ServiceA want to read ServiceB's title property set in com.example.serivce.impl.ServiceB.xml
Then in ServiceB in the #activate method read the props from OCD config and set it in instance level and have ServiceA inject ServiceB as it's dependency and use the property needed.
eg.
class ServiceA{
#Reference
private ServiceB serviceB;
public void someMethod(){
serviceB.getTitle(); // Successfully read property of another service i.e.
ServiceB without using ConfigurationAdmin.
}
}

Spring overwriting controller

I provide a highly customisable application to my clients which is working totally by itself. But If one my client wants to overwrite any Controller, I want to replace my implementation by theirs. However just overwriting the controller causes an ambiguous definition of mappings.
I have been using Component Scanning to load beans.
The potential solutions came to my mind are:
Using component scanner with excluding by a custom filter? (This seems not so easy)
Using a xxxxPostProcessor to remove some beans? (How?)
Any help?
If I got your Question properly,
You can differ implementation by changing URL to particular Implementation name
Say Telecom is interface and AirtelImpl and RelianceImpl are Controllers then
Your request mapping
#RequestMapping(value= "/airtel/doBilling")
#RequestMapping(value= "/reliance/doBilling")
In this way, Implementation flow will differ.
I have followed these steps:
Created a custom annotation: #Devoted
Created a custom ImportBeanDefinitionRegistrar. Iterated already registered bean definitions to find out `#Devoted #Controller's and removed them.
Based on a request I will provide implementation details.

Webapi DefaultHttpControllerSelector does not properly resolve my controller

I have an WebApi application that contains some controllers (they are registered using the extension method RegisterApiControllers). This application references another assembly that contains other controllers that I don't want to expose(I have checked that they are not registered in the container). It happens that both have an OrderController, and when I try to access the /api/Order url, I get an exception "Multiple types were found that match the controller named 'order'." and the stack trace shows that I was in DefaultHttpControllerSelector.
I have seen that AutofacControllerFactory used to exist and there was even a ConfigureWebApi that registered it, but it is not anymore present in the default branch.(you can see it here http://alexmg.com/post/2012/03/09/Autofac-ASPNET-Web-API-(Beta)-Integration.aspx)
It seems also that we can not filter the namespace of the route definition in WebApi (it is possible to MVC).
So any idea on how I can use only the Controller registered in my Autofac container and not use the DefaultHttpControllerSelector that seems to scan all referenced assemblies to discover controller?
Thanks
The problem is that registering the controller with autofac is not really related to the routing process. Only once the routing process has identified which controller to dispatch to will Autofac be called to resolve the type.
It looks like, from digging around in the source, that you would need to write a replacement IHttpControllerSelector in order to handle two controllers with the same name. (which really sucks BTW).
You might be able replace the DefaultHttpControllerTypeResolver with an instance that is passed a predicate that filters out the controllers from the assembly that you want to ignore. It's a bit of a kludgy solution but might work.
Actually, you might be able to replace the DefaultHttpControllerTypeResolver completely with one that is based on registrations in your Autofac container. It is a very simple interface, so as long as Autofac have a some kind of discovery mechanism, you should be golden.
public interface IHttpControllerTypeResolver
{
ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver);
}

Regarding Symfony2 Session

In symfony2 every user created controller extends Controller Class as shown below,
class MyController extends Controller {
thus functions related to session handling are available with $this object, But controllers in Vendor and Core don't extend Controller class thus don't provide access to session related functions. So is there any way to use these functions without extending Controller class.
Presently I am using $_SESSION[], for setting and getting session variables.
Is there any way other than above.
Symfony2 provides a service for sessions, this is what you're trying to retrieve. All services in symfony2 are retrieved using the service container, which is what you're referring to with
$this->get('session');
To properly make use of the service container in your own controllers you can either...
Configure your controllers as services (see: here)
Extend the base Controller class provided by the Symfony2 stack (making the get() method available to your child Controller)
The first option is the correct way to go, you have full control over what services are then injected into your respective controllers (see service container documentation)

Stop Caching IControllerActivator

Is there a way to configure the MVC3 *DependencyResolver* to stop caching the resolved IControllerActivator. I have several containers and multiple implementations of IControllerActivator registered.
Unfortunately the DependencyResolver is not always called to resolve the correct IControllerActivator. I suspect caching.
Any idea ?
There is no way to do that. You would have to write your own implementation of IControllerFactory (perhaps deriving from DefaultControllerFactory) or write a delegating IControllerActivator that dynamically looks up your desired activator and invokes it.

Resources