I am attempting to read the content of a file in Alfresco. I have seen examples that use
ContentService. Unforunately, when I try to use the example code, the ContentService
is not available.
I have added ContentService as a managed property of my managed bean in faces-config.xml
<managed-property>
<property-name>contentService</property-name>
<value>#{ContentService}</value>
</managed-property>
In my java code, I am using
ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
final ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
// contentService is an instance variable.
this.contentService = serviceRegistry.getContentService();
I am getting this Exception:
javax.faces.el.EvaluationException: Exception while invoking expression #{DeployAssetQADialog.start}
caused by:
javax.faces.el.PropertyNotFoundException: Bean: com.XXXXXXXXXX.CCCCCCCC.DeployAssetDialog, property: contentService
Can anyone tell me if there is something that I am missing? Thanks
PropertyNotFoundException sounds like your managed bean is missing a setter method.
How to expose spring managed beans to jsf may depend on the spring and/or jsf version you are using. Have a look at Spring beans injected into JSF Managed Beans for an example.
Finally, Make sure your Alfresco spring context is initialized before jsf kicks in.
Many issues in code
1) For each services which are injected you need to add getter setter method for them.
If you add getter setter for contentservice you can get rid of your error.
2) Other thing is you are trying to get conentservice though service registry in that case you need to inject service registry and add getter setter for that. Otherwise get contentservice instance directly as it is injected though faces-config and provided you have added getter setter for it you can directly use that instance of contentservice.
Related
I am trying to change ConsumerConfig properties by making change in a property file, which will be watched by #scheduled method( this will look for change in any property value and re-initialize the consumer after updating container factory bean instance picked from application context).
For example: If new broker is added to cluster, I would simply update broker list in property file.
The KafkaConsumer and its ConsumerConfig comes from the DefaultKafkaConsumerFactory into the KafkaMessageListenerContainer.
The DefaultKafkaConsumerFactory is injected with the Map of configs for the consumer. I think this is exactly the place where you should consider to change properties from your #Scheduled method. After changing them you should stop() listener container(s) and start() again - a new KafkaConsumer will be created based on fresh configs.
However a consumerGroupId indeed should be changed via ContainerProperties.
For this purpose there is just enough to change it via MessageListenerContainer.getContainerProperties().setGroupId(String groupId).
I have the same EJB module with a bean inside an EAR that is server side and an EAR that is the client side.
Can I have this situation?
Because I'm getting this error http://justpaste.it/gfs3
without understand how to fix it.
You have answer in the stack trace:
The short-form default binding 'com.demo.view.RitornaPersonaRemote'
is ambiguous because multiple beans implement the interface :
[RitornaPersonaSenzaClientEAR#RitornaPersonaSenzaClient.jar#RitornaPersona,
RitornaPersonaWebSenzaClientEAR#RitornaPersonaSenzaClient.jar#RitornaPersona].
Provide an interface specific binding or use the long-form default binding on lookup.]
If you are asking whether you may have same EJB jar in multiple project - the answer is yes you can. However during deployment you have to use long-form JNDI, provide different JNDI name for beans in other module or disable short names. You cannot register two beans under same name.
Long name would be in the form RitornaPersonaSenzaClientEAR#RitornaPersonaSenzaClient.jar#com.demo.view.RitornaPersonaRemote
See detailed info here - EJB 3.0 and EJB 3.1 application bindings overview
UPDATE
To disable short names perform the following steps:
Go to Application servers > server1 > Process definition > Java Virtual Machine > Custom properties
Define new custom property com.ibm.websphere.ejbcontainer.disableShortDefaultBindings with value * to disable short bindings for all apps or AppName1|AppName2 to just disable short bindings in selected apps.
Example default bindings are shown in SystemOut.log:
The binding location is: ejblocal:JPADepEar/JPADepEJB.jar/TableTester#ejb.TableTester
The binding location is: ejblocal:ejb.TableTester
The binding location is: java:global/JPADepEar/JPADepEJB/TableTester!ejb.TableTester
And with disableShortDefaultBindings property set there is no short form:
The binding location is: ejblocal:JPADepEar/JPADepEJB.jar/TableTester#ejb.TableTester
The binding location is: java:global/JPADepEar/JPADepEJB/TableTester!ejb.TableTester
There is a bug in the documentation and the correct property is com.ibm.websphere.ejbcontainer.disableShortDefaultBindings not com.ibm.websphere.ejbcontainer.disableShortFormBinding
In my case:- i did install abc.ear and xyz.ear both ear was independent do dependency with each other.
I was calling abc.ear using client-lookup but that was giving me
com.ibm.websphere.naming.CannotInstantiateObjectException: Exception occurred while the JNDI NamingManager was processing a javax.naming.Reference object.
[Root exception is com.ibm.websphere.ejbcontainer.AmbiguousEJBReferenceException: The short-form default binding
'com.ejb.abc' is ambiguous because multiple beans implement the interface :
[xyz-ear#rabc-ejb-1.0.jar#abcInrerfaceImpl, rabc-ear#rabc-ejb-1.0.jar
abcInrerfaceImpl]. Provide an interface specific binding or use the long-form default binding on lookup.]
my Solution was:-
i removed the abc.jar that was inside another application(xyz.ear)
C:\Program Files\IBM\WebSphere\AppServer\profiles\AppSrv01\wstemp\92668751\workspace\cells\mypc00Node01Cell\applications\xyz-ear.ear
'
Then solution client-lookup works fine.
To avoid this in future this is better practice to create separate node on your IBM-WAS server and install both application on different node.
So both application component will not mess up.
I can't find the answer to this...
If I inject the service container, like:
// config.yml
my_listener:
class: MyListener
arguments: [#service_container]
my_service:
class: MyService
// MyListener.php
class MyListener
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function myFunction()
{
$my_service = $this->container->get('my_service');
$my_service->doSomething();
}
}
then it works just as well as if I do:
// config.yml
my_listener:
class: MyListener
arguments: [#my_service]
my_service:
class: MyService
// MyListener.php
class MyListener
{
protected $my_service;
public function __construct(MyService $my_service)
{
$this->my_service = $my_service;
}
public function myFunction()
{
$this->my_service->doSomething();
}
}
So why shouldn't I just inject the service container, and get the services from that inside my class?
My list of reasons why you should prefer injecting services:
Your class is dependent only on the services it needs, not the service container. This means the service can be used in an environment which is not using the Symfony service container. For example, you can turn your service into a library that can be used in Laravel, Phalcon, etc - your class has no idea how the dependencies are being injected.
By defining dependencies at the configuration level, you can use the configuration dumper to know which services are using which other services. For example, by injecting #mailer, then it's quite easy to work out from the service container where the mailer has been injected. On the other hand, if you do $container->get('mailer'), then pretty much the only way to find out where the mailer is being used is to do a find.
You'll be notified about missing dependencies when the container is compiled, instead of at runtime. For example, imagine you have defined a service, which you are injecting into a listener. A few months later, you accidentally delete the service configuration. If you are injecting the service, you'll be notified as soon as you clear the cache. If you inject the service container, you'll only discover the error when the listener fails because of the container cannot get the service. Sure, you could pick this up if you have thorough integration testing, but ... you have got thorough integration testing, haven't you? ;)
You'll know sooner if you are injecting the wrong service. For example, if you have:
public function __construct(MyService $my_service)
{
$this->my_service = $my_service;
}
But you've defined the listener as:
my_listener:
class: Whatever
arguments: [#my_other_service]
When the listener receives MyOtherService, then PHP will throw an error, telling you that it's receiving the wrong class. If you're doing $container->get('my_service') you are assuming that the container is returning the right class, and it can take a long time to figure out that its' not.
If you're using an IDE, then type hinting adds a whole load of extra help. If you're using $service = $container->get('service'); then your IDE has no idea what $service is. If you inject with
public function __construct(MyService $my_service)
{
$this->my_service = $my_service;
}
then your IDE knows that $this->my_service is an instance of MyService, and can offer help with method names, parameters, documentation, etc.
Your code is easier to read. All your dependencies are defined right there at the top of the class. If they are scattered throughout the class with $container->get('service') then it can be a lot harder to figure out.
Your code is easier to unit test. If you're injecting the service container, you've got to mock the service container, and configure the mock to return mocks of the relevant services. By injecting the services directly, you just mock the services and inject them - you skip a whole layer of complication.
Don't be fooled by the "it allows lazy loading" fallacy. You can configure lazy loading at configuration level, just by marking the service as lazy: true.
Personally, the only time injecting the service container was the best possible solution was when I was trying to inject the security context into a doctrine listener. This was throwing a circular reference exception, because the users were stored in the database. The result was that doctrine and the security context were dependent on each other at compile time. By injecting the service container, I was able to get round the circular dependency. However, this can be a code smell, and there are ways round it (for example, by using the event dispatcher), but I admit the added complication can outweigh the benefits.
Besides all disadvantages explained by others (no control over used services, run time compilation, missing dependencies, etc.)
There is one main reason, which breaks the main advantage of using DIC - Dependencies replacement.
If service is defined in library, you wont be able to replace it dependencies with local ones filling your needs.
Only this reason is strong enough, to not inject whole DIC. You just break whole idea of replacing dependencies since they are HARDCODED! in service;)
BTW. Don't forget to require interfaces in service constructor instead of specific classes as much as you can - again nice dependencies replacement.
EDIT: Dependencies replacement example
Service definition in some vendor:
<service id='vendor_service' class="My\VendorBundle\SomeClass" />
<argument type="service" id="vendor_dependency" />
</service>
Replacement in your app:
<service id='vendor_service' class="My\VendorBundle\SomeClass" />
<argument type="service" id="app_dependency" />
</service>
This allows you to replace vendor logic with your customized one, but don't forget to implement required class interface. With hardcoded dependencies you're not able to replace dependency in one place.
You can also override vendor_dependency service, but this will replace it in all places not only in vendor_service.
It is not a good idea because you're making your class dependent on the DI. What happens when some day you decide to pull out your class and use it on an entirely different project? Now I'm not talking about Symfony or even PHP, I'm talking generally. So in that case you have to make sure the new project uses the same kind of DI mechanism with the same methods supported or you get exceptions. And what happens if the project does not use DI at all, or uses some cool new DI implementation? You have to go through your whole codebase and change things to support the new DI. In large projects this can be problematic and costly, especially when you're pulling more than just one class.
It is best to make your classes as independent as possible. This means keeping the DI out of your usual code, something like a 3rd person who decides what goes where, points where the stuff should go, but doesn't go there and do it himself. This is how I understand it.
Although, as tomazahlin said, I agree that in Symfony projects in rare occasion it helps prevent circular dependencies. That's the only example where I'd use it and I'd make damn sure that's the only option.
Injecting the whole container is not a good idea in general. Well, it works, but why injecting the whole container, while you only need a few other services or parameters.
Sometimes you want to inject the whole container to avoid circular references, because if you inject the whole container, you get "lazy loading" of the services you require. An example would be doctrine entity listeners.
You can get the container from every class that is "Container Aware" or has access to the kernel.
Is there a way to access the configuration parameters in config.yml from the model layer? From the controller I can use $this->container->getParameter('xyz'). But how can it be done from a class in the Model layer?
In symfony2 Entities are designed as POPOs, meaning that they shouldn't really have access to anything outside of their scope.
If you need some config option in one of your entities, consider passing it as a parameter from the controller like so:
$entityName->methodName($param1, $this->container->getParameter('xyz'));
This could (will) break DIC pattern, but you could use a singleton class to "globalize" what you need.
To feed your globals, use bootmethod from Bundle class (where you can access DIC stuff hence configuration).
Or more simple, add a static field to your Entity.
Quick & dirty solution, don't abuse it ;-)
You can use Dependency Injection and add your model to your services.yml file, and like every other service you make you can provide other services as constructor parameters. The only downside is you call $derp = $this->get("your_service_name"); instead of $derp = new Derp();.
For example:
# src/Derp/LolBundle/Resources/config/services.yml
services:
derp:
class: \Derp\LolBundle\Entity\Message
arguments: [#service_container]
#service_container is a service found using php app/console container:debug. It will function identically to $this->container in your controllers and it is provided to the constructor of your class. See here for more information on how to use service containers.
As previously mentioned they are POPOs (Plain Old PHP Objects) and the previous method of dependency injection is poor choice simply because you will have to remember to provide your model entity with the same object every time you use it (which is a hassle) and Symfony2 services are a way to mitigate that pain.
I'm building a site that relies quite heavily on a third party API so I thought it would make sense to package up the API wrapper as a service, however I'm starting to find instances where it would be useful to have access to it outside of a controller such as in an entity repository.
Also related to that is it would be useful to be able to get access to config values outside of a controller (again such as in an entity repository).
Can anyone tell me if this is possible and if not is there a suggested approach to doing this kind of thing?
thanks for any help
The Symfony distribution relies heavily on dependency injection. This means that usually, dependencies are injected directly into your object via the constructor, the setters or via other means (like reflection over properties). Your API wrapper service is then a dependency for other objects of your application.
That being said, it would be rather difficult to inject this service in an entity repository's constructor because it already requires some other parameters and I think it would not be possible to inject them because of the way we request the repository for an entity.
What you could do is to create another service which will be responsible of doing the work you were about to do in the entity repository. This way, you will be able to inject the entity manager, which will be used to retrieve the entity repository, you custom service and also another service holding your configuration values (There are other ways to share configuration values).
In my use case, I use a Facebook helper service that wraps Facebook API calls. This service is then injected where I need it. My entity repository is only responsible of doing database calls so it receives only the arguments it needs and not the whole dependency. Thus, it will not receive the helper but rather only the arguments needed to do a request, for example, a Facebook user id. In my opinion, this is the way to do it since I think the entity repository should not have dependencies on such helper objects.
Here a small example using YAML as the configuration:
# app/config/config.yml
services:
yourapp.configuration_container:
class: Application/AcmeBundle/Common/ConfigurationContainer
# You could inject configurations here
yourapp.api_wrapper:
class: Application/AcmeBundle/Service/ApiWrapperService
# Inject other arguments if needed and update constructor in consequence
yourapp.data_access:
class: Application/AcmeBundle/Data/Access/DatabaseAccessService
arguments:
entityManager: "#doctrine.orm.entity_manager"
apiWrapperService: "#yourapp.api_wrapper"
configuration: "#yourapp.configuration_container"
# Application/AcmeBundle/Common/ConfigurationContainer.php
public ConfigurationContainer
{
public function __construct()
{
// Initialize your configuration values or inject them in the constructor
}
}
# Application/AcmeBundle/Service/ApiWrapperService.php
public ApiWrapperService
{
public function __construct()
{
// Do some stuff
}
}
# Application/AcmeBundle/Data/Access/DatabaseAccessService.php
public DatabaseAccessService
{
public function __construct(EntityManager $entityManager, ApiWrapperService $apiWrapperService, ConfigurationContainer $configuration)
{
...
}
}
The at sign (#) in the config.yml file means that Symfony should inject another service ,having the id defined after the at sign, and not a simple string. For the configuration values, as I said previously, there is other means to achieve the same goal like using parameters or a bundle extension. With a bundle extension, you could define the configuration values directly into the config.yml and your bundle would read them.
In conclusion, this should give you the general idea of injecting services. Here a small list of documentation on the subject. Alot of links use the XML service definition instead of the YAML definition but you should be able to understand them quite easily.
Symfony Official DI
Fabien Potencier's articles on DI
Richard Miller's articles on DI (Check in his blog for the other DI articles)
Take note that the configuration I'm giving is working for Beta1 of Symfony2. I didn't update yet to Beta2 so there could be some stuff not working as they are in the Beta2 version.
I hope this will help you defining a final solution to your problem. Don't hesitate to ask other questions if you want clarifications or anything else.
Regards,
Matt
I would wrap this kind of behavior in a Symfony service(like a manager).
i would not inject any parameters or logic into the entity repositories, as they should mainly be used to fetch data using object manager queries.
I would put the logic in the services and if the service , require a database access it will call the entity repository to fetch data.