Ask Questions and Find Answers
Important:
Ask is now read-only. You can review any existing questions and answers, but not add anything new.
But - don't panic! While ask is no more, we've replaced it with discuss - the new Liferay Discussion Forum! Read more here here or just visit the site here:
discuss.liferay.com
RE: Calling LocalService in a non controller class
Hi,
When I try to call a service (generated by serviceBuilder) from a class that is not a @Component, when the call is executed, I give the followin error
"EndpointRegistration[{"patterns":["/portlet-servlet/*"], "name":"com.lifer...etServlet", "servletInfo":"", "asyncSupported":false, "initParams":{}, "servletContextId":7594, "serviceId":7602}]"
"WebappClassLoader
context: ROOT
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@2d6e8792
"
The same call executed in a @Component class works properly.
I have the following sentences:
When I try to call a service (generated by serviceBuilder) from a class that is not a @Component, when the call is executed, I give the followin error
"EndpointRegistration[{"patterns":["/portlet-servlet/*"], "name":"com.lifer...etServlet", "servletInfo":"", "asyncSupported":false, "initParams":{}, "servletContextId":7594, "serviceId":7602}]"
"WebappClassLoader
context: ROOT
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@2d6e8792
"
The same call executed in a @Component class works properly.
I have the following sentences:
private SubTipoSubscripcionLocalService subTipoSubscripcionLocalService;
@Reference(unbind = "-")
public void setSubTipoSubscripcionLocalService(SubTipoSubscripcionLocalService subTipoSubscripcionLocalService) {
this.subTipoSubscripcionLocalService = subTipoSubscripcionLocalService;
}
any idea?
Probably the service is simply null.
Add some log output to setSubTipoSubscripcionLocalService, I guess it is never set.
Could you check, if that is the case? If yes, you could try to use the Util class.
Add some log output to setSubTipoSubscripcionLocalService, I guess it is never set.
Could you check, if that is the case? If yes, you could try to use the Util class.
Iñigo BoyanoHi,I'm assuming that you're obtaining the service through a @Reference annotation? @Reference is only resolved in @Component classes, not outside. So you'll need to find another method to pass the service reference to the methods in question explicitly.
When I try to call a service (generated by serviceBuilder) from a class that is not a @Component, when the call is executed, I give the followin error
Hi Olaf,
If I make the call in a *LocalServiceUtils instead of LocalService, the method works properly but, searching about good practices, i fount that is not properly to use the classes *LocalServiceUtils to call services outside @Component class in Liferay 7.0. (https://community.liferay.com/es/forums/-/message_boards/message/83433590#_com_liferay_message_boards_web_portlet_MBPortlet_message_83437418)
I think is not properly either to make a Utils class a @Component, right? So, how is the best way to access services methods in a Utils Class?
Thanks Olaf,
Kind Regards,
If I make the call in a *LocalServiceUtils instead of LocalService, the method works properly but, searching about good practices, i fount that is not properly to use the classes *LocalServiceUtils to call services outside @Component class in Liferay 7.0. (https://community.liferay.com/es/forums/-/message_boards/message/83433590#_com_liferay_message_boards_web_portlet_MBPortlet_message_83437418)
I think is not properly either to make a Utils class a @Component, right? So, how is the best way to access services methods in a Utils Class?
Thanks Olaf,
Kind Regards,
Iñigo BoyanoIf you talk about Liferay's service-Util classes: They have all static methods anyways, so there's no value in making them a @Component.
If I make the call in a *LocalServiceUtils instead of LocalService, the method works properly but, searching about good practices, i fount that is not properly to use the classes *LocalServiceUtils to call services outside @Component class in Liferay 7.0. (https://community.liferay.com/forums/-/message_boards/message/83433590)
I think is not properly either to make a Utils class a @Component, right? So, how is the best way to access services methods in a Utils Class?
My recommendation would be to either add the service as a parameter, or initialize (and uninitialize) them from any other @Component's initialization, e.g. @Activate method or in the @Reference's setter. Make sure that you also uninitialize the objects when the service is signalled to go away. You simply shouldn't use servicebuilder's *ServiceUtil classes, because they effectively hide your dependency on the actual service.
Iñigo BoyanoIn general, using OSGi methods to access OSGi components is a best practice.
If I make the call in a *LocalServiceUtils instead of LocalService, the method works properly but, searching about good practices, i fount that is not properly to use the classes *LocalServiceUtils to call services outside @Component class in Liferay 7.0.
For your own @Component classes, this means @Reference'ing the *LocalService and have OSGi just inject it for you.
For non @Component classes, this can mean using a ServiceTracker to get an instance when you need it (you don't hold the instance, you only hold the tracker and get the *LocalService from the tracker to complete a call).
The *LocalServiceUtil classes are holdovers from 6.x and earlier days. They suffice for helping to upgrade legacy code while minimizing change.
They have one big problem though - they throw NPEs when invoked at the wrong time because they actually do not know about the availability of the service to invoke.
For example, I can deploy an API module with a service, FailLocalService and its corresponding FailLocalServiceUtil. Now lets say I do not deploy the service module or, even worse, I deployed it but it has some kind of issue and it didn't start and I just haven't seen the error yet. Either way, my implementation of FailLocalService is not going to be available.
I can deploy code that uses an @Reference or a ServiceTracker to get the FailLocalService, in each case I will know about the lack of an implementation. The @Component just won't start and the ServiceTracker will know that there is no available service, so as the developer I have visibility on the fact the service is not available to use.
But code I write that uses FailLocalServiceUtil? That code will start and I will have no idea the service is really not available. Until, of course, my code invokes a FailLocalServiceUtil method and I get a mysterious NullPointerException and a stack trace pointing at the FailLocalServiceUtil.
That is why I recommend not using the *LocalServiceUtil classes in most cases. For upgrades, sure, because you want to minimize time, cost and impact when getting the upgrade done. But for any new development, it is worth getting the OSGi lookups in there and getting them right because it prevents a runtime failure due to a missing service instance.
Hi david,
First to answer to Olaf, declaring the services in a @Component class and passing them as params to my Utils class methods works properly.
However when i try to implement a getter in my own entity to get another entity, the easiest way to do it is by using *LocalServiceUtil like Liferay would use it in its own code.
E.g. You have the UserImpl Class to get the Contact entity. To develop it i have seen that you use the next sentence in your UserImpl.java
Kind regards,
Íñigo.
First to answer to Olaf, declaring the services in a @Component class and passing them as params to my Utils class methods works properly.
However when i try to implement a getter in my own entity to get another entity, the easiest way to do it is by using *LocalServiceUtil like Liferay would use it in its own code.
E.g. You have the UserImpl Class to get the Contact entity. To develop it i have seen that you use the next sentence in your UserImpl.java
@Override
public Contact fetchContact() {
if (_contact == _NULL_CONTACT) {
return null;
}
if (_contact == null) {
Contact contact = ContactLocalServiceUtil.fetchContact(
getContactId());
if (contact == null) {
_contact = _NULL_CONTACT;
}
else {
_contact = contact;
}
}
return _contact;
}
Is there any way to develop this without using *LocalServiceUtil or it's correct to call LocalServiceUtils in a Model Impletementation Layer like you have in your kernel?Kind regards,
Íñigo.
Iñigo BoyanoNo. The kernel can get away with it, as those are most likely kernel provided services. And when the kernel is there, the services will be there. But as soon as they're migrated out, they might run into the problems that David describes above.
Is [...] it[...] correct to call LocalServiceUtils in a Model Impletementation Layer like you have in your kernel?
Even if you find *LocalServiceUtil calls outside of the kernel, in modules: I'd call that a bug. Maybe a potential bug.
Is there any way to develop this without using *LocalServiceUtil or it's correct to call LocalServiceUtils in a Model Impletementation Layer like you have in your kernel?No, that's like the one place that I have not been able to find a way around avoiding the *LocalServiceUtil classes.
The *ModelImpl's are instantiated internally by SB and Hibernate, so there's no entry point to inject services.
I've tried overriding and injecting at the *LocalServiceImpl or in a ServiceWrapper as that's a way to get an external service wired in and provide it to the model, but that breaks down if/when you are pulling a list in bulk.
Copyright © 2025 Liferay, Inc
• Privacy Policy
Powered by Liferay™