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: Liferay Guestbook Web Application - entryLocalService cannot be resolve
I'm following the Guestbook tutorial in https://portal.liferay.dev
I think that the 7.1 tutorial Liferay Guestbook Web Application is wrong.
After developed the services including Guestbook and Entity entities I wrote the custom service methods.
But exactly following the Liferay's tutorials, I get an error in GuestbookLocalServiceImpl telling me that I can't use methods from Entity's services.
I can't use the entryLocalService object and I get the "entryLocalService cannot be resolved" error.
entryLocalService.getEntries() ---> error
But of course I can use the EntryLocalServiceUtil methods:
EntryLocalServiceUtil.getEntries() ---> OK
I'm brand new to OSGi development and very probable I'm missing something from build.gradle dependencies:
dependencies {
compileOnly group: "com.liferay", name: "com.liferay.petra.lang"
compileOnly group: "com.liferay", name: "com.liferay.petra.string"
compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"
compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"
compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"
compileOnly group: "org.osgi", name: "org.osgi.core"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"
compileOnly project(":modules:guestbook:guestbook-api")
}
buildService {
apiDir = "../guestbook-api/src/main/java"
}
group = "mc.infocomm.ipl.test.guestbook"
Please anyone can help me ?
Ivano C.
I think that the 7.1 tutorial Liferay Guestbook Web Application is wrong.
After developed the services including Guestbook and Entity entities I wrote the custom service methods.
But exactly following the Liferay's tutorials, I get an error in GuestbookLocalServiceImpl telling me that I can't use methods from Entity's services.
I can't use the entryLocalService object and I get the "entryLocalService cannot be resolved" error.
entryLocalService.getEntries() ---> error
But of course I can use the EntryLocalServiceUtil methods:
EntryLocalServiceUtil.getEntries() ---> OK
I'm brand new to OSGi development and very probable I'm missing something from build.gradle dependencies:
dependencies {
compileOnly group: "com.liferay", name: "com.liferay.petra.lang"
compileOnly group: "com.liferay", name: "com.liferay.petra.string"
compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"
compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"
compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"
compileOnly group: "org.osgi", name: "org.osgi.core"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"
compileOnly project(":modules:guestbook:guestbook-api")
}
buildService {
apiDir = "../guestbook-api/src/main/java"
}
group = "mc.infocomm.ipl.test.guestbook"
Please anyone can help me ?
Ivano C.
Attachments:
How did you include the Entry service in your Guestbook layer? Via the <reference /> tag in the Guestbook's <entity />?
Dear David, thank you for your reply.
I just tried to add the below in service.xml:
<reference entity="Entry" package-path="mc.infocomm.ipl.test.guestbook" />
The builService Gradle task ends without errors:
> Task :modules:guestbook:guestbook-service:buildService
Building Entry
Building Guestbook
Writing ..\guestbook-api\src\main\java\mc\infocomm\ipl\test\guestbook\service\GuestbookLocalService.java
Writing ..\guestbook-api\src\main\java\mc\infocomm\ipl\test\guestbook\service\GuestbookLocalServiceUtil.java
Writing ..\guestbook-api\src\main\java\mc\infocomm\ipl\test\guestbook\service\GuestbookLocalServiceWrapper.java
Writing src\main\resources\service.properties
but still the Entry's methods remain unresolved.
I just tried to add the below in service.xml:
<reference entity="Entry" package-path="mc.infocomm.ipl.test.guestbook" />
The builService Gradle task ends without errors:
> Task :modules:guestbook:guestbook-service:buildService
Building Entry
Building Guestbook
Writing ..\guestbook-api\src\main\java\mc\infocomm\ipl\test\guestbook\service\GuestbookLocalService.java
Writing ..\guestbook-api\src\main\java\mc\infocomm\ipl\test\guestbook\service\GuestbookLocalServiceUtil.java
Writing ..\guestbook-api\src\main\java\mc\infocomm\ipl\test\guestbook\service\GuestbookLocalServiceWrapper.java
Writing src\main\resources\service.properties
but still the Entry's methods remain unresolved.
In your GuestbookLocalServiceImpl, you should be able to use autocomplete to find an instance of entryLocalService that is available from a superclass...
It is via this entryLocalService that you get access to the Entry services.
It is via this entryLocalService that you get access to the Entry services.
Dear David,
You was so gentle to address me to the problem.
But still I'm in trouble because do a Ctrl-space for autocomplete but I get the list of EntryLocalService* classes and also the assetEntryLocalService but no entryLocalService methods.
For example in the code I can see userLocalService.getUser() method in blue color but entryLocalService methods are unusable.
I think that beside autocomplete there is something missing in the tutorial about to reference the Entry methods from inside the Guestbook services.
Thank you in advance for some more helps.
Ivano C.
You was so gentle to address me to the problem.
But still I'm in trouble because do a Ctrl-space for autocomplete but I get the list of EntryLocalService* classes and also the assetEntryLocalService but no entryLocalService methods.
For example in the code I can see userLocalService.getUser() method in blue color but entryLocalService methods are unusable.
I think that beside autocomplete there is something missing in the tutorial about to reference the Entry methods from inside the Guestbook services.
Thank you in advance for some more helps.
Ivano C.
Well, it absolutely works, I've done it before.
And now that I think about it, the <reference /> tag isn't necessary either, ServiceBuilder should auto-inject all of the entity local service and persistence objects for all entities in the service.xml file.
Are you sure you're not looking at "entryLocalService" and may in fact be looking at "entryService", the remote service for Entries? The remote service always starts out with no methods, so it kind of sounds like this might be playing a role?
And now that I think about it, the <reference /> tag isn't necessary either, ServiceBuilder should auto-inject all of the entity local service and persistence objects for all entities in the service.xml file.
Are you sure you're not looking at "entryLocalService" and may in fact be looking at "entryService", the remote service for Entries? The remote service always starts out with no methods, so it kind of sounds like this might be playing a role?
Dear David,
I removed the <reference /> tag from the service.xml file.
The below is the class code:
public Guestbook deleteGuestbook(long guestbookId, ServiceContext serviceContext) throws PortalException, SystemException {
Guestbook guestbook = getGuestbook(guestbookId);
List<Entry> entries = entryLocalService.getEntries(serviceContext.getScopeGroupId(), guestbookId); // entryLocalService cannot be resolved
for (Entry entry : entries) {
entryLocalService.deleteEntry(entry.getEntryId()); // entryLocalService cannot be resolved
}
guestbook = deleteGuestbook(guestbook);
return guestbook;
}
The below is the build.grade in the guestbook-service module:
dependencies {
compileOnly group: "com.liferay", name: "com.liferay.petra.lang"
compileOnly group: "com.liferay", name: "com.liferay.petra.string"
compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"
compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"
compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"
compileOnly group: "org.osgi", name: "org.osgi.core"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"
compileOnly project(":modules:guestbook:guestbook-api")
}
buildService {
apiDir = "../guestbook-api/src/main/java"
}
group = "mc.infocomm.ipl.test.guestbook"
Please could you help me more ?
Ivano C.
I removed the <reference /> tag from the service.xml file.
The below is the class code:
public Guestbook deleteGuestbook(long guestbookId, ServiceContext serviceContext) throws PortalException, SystemException {
Guestbook guestbook = getGuestbook(guestbookId);
List<Entry> entries = entryLocalService.getEntries(serviceContext.getScopeGroupId(), guestbookId); // entryLocalService cannot be resolved
for (Entry entry : entries) {
entryLocalService.deleteEntry(entry.getEntryId()); // entryLocalService cannot be resolved
}
guestbook = deleteGuestbook(guestbook);
return guestbook;
}
The below is the build.grade in the guestbook-service module:
dependencies {
compileOnly group: "com.liferay", name: "com.liferay.petra.lang"
compileOnly group: "com.liferay", name: "com.liferay.petra.string"
compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"
compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"
compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"
compileOnly group: "org.osgi", name: "org.osgi.core"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"
compileOnly project(":modules:guestbook:guestbook-api")
}
buildService {
apiDir = "../guestbook-api/src/main/java"
}
group = "mc.infocomm.ipl.test.guestbook"
Please could you help me more ?
Ivano C.
That is the exact chunk of code and it should work, but it's failing for you?
Did you rebuild services after changing the service.xml and the classes?
How is the failure manifesting itself? Is it just the IDE reporting errors or did you actually try deploying the code?
Did you rebuild services after changing the service.xml and the classes?
How is the failure manifesting itself? Is it just the IDE reporting errors or did you actually try deploying the code?
Yes I rebuilt the services.
There are errors in IDE and the container doesn't activate the guestbook-service module cause the compile errors
There are errors in IDE and the container doesn't activate the guestbook-service module cause the compile errors
Okay, so when you try to start the bundle in gogo, what is reported?
Dear David,
I'm deployng the test modules in Eclipse IDE - attached here you can see the error mark of guestbook-service in Servers panel of the IDE.
Maibe I have to delete the project and restart from scratch but I'm a bit worried since this big issue in a so simple module.
Ivano C.
I'm deployng the test modules in Eclipse IDE - attached here you can see the error mark of guestbook-service in Servers panel of the IDE.
Maibe I have to delete the project and restart from scratch but I'm a bit worried since this big issue in a so simple module.
Ivano C.
Attachments:
A red X doesn't do anything to diagnose the issue...
Can you get into the Gogo shell (telnet localhost 11311 if on 7.0 or use the Gogo control panel in 7.1+), use the lb command to find the service, then start XXX to start the bean w/ the matching id?
That will give you the detailed OSGi reason why the bundle cannot start. It's from that point that we'll diagnose and resolve the issue.
Can you get into the Gogo shell (telnet localhost 11311 if on 7.0 or use the Gogo control panel in 7.1+), use the lb command to find the service, then start XXX to start the bean w/ the matching id?
That will give you the detailed OSGi reason why the bundle cannot start. It's from that point that we'll diagnose and resolve the issue.
Dear David,
After I dragged the guestbook-api and guestbook-service from the Project Explorer to the running Tomcat bundle, only guestbook-api is present in the lb command output in the Gogo shell:
2150|Active | 1|guestbook-api (1.0.0)|1.0.0
So I can't try to start guestbook-service because it is not present.
Thank you for your support !
Ivano
After I dragged the guestbook-api and guestbook-service from the Project Explorer to the running Tomcat bundle, only guestbook-api is present in the lb command output in the Gogo shell:
2150|Active | 1|guestbook-api (1.0.0)|1.0.0
So I can't try to start guestbook-service because it is not present.
Thank you for your support !
Ivano
Okay, let's try something different.
If you open a command prompt in the guestbook-service module and attempt to build it, what is the generated output?
If you open a command prompt in the guestbook-service module and attempt to build it, what is the generated output?
Dear David,
I executed the gradlew.bat buildService command from the root of the project.
I'm not able to tun Gradle commands from other folders. I'm using only the Gradle wrapped in the IDE.
Below what I done and no errors building services:
C:\dev\liferay\7.2.0-ce-ga1\ipl-workspace\mc-infocomm-ipl>gradlew.bat buildService
> Task :modules:guestbook:guestbook-service:buildService
Building Entry
Building Guestbook
Writing src\main\resources\service.properties
BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed
I executed the gradlew.bat buildService command from the root of the project.
I'm not able to tun Gradle commands from other folders. I'm using only the Gradle wrapped in the IDE.
Below what I done and no errors building services:
C:\dev\liferay\7.2.0-ce-ga1\ipl-workspace\mc-infocomm-ipl>gradlew.bat buildService
> Task :modules:guestbook:guestbook-service:buildService
Building Entry
Building Guestbook
Writing src\main\resources\service.properties
BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed
So it builds the services fine, how about just a complete build using "gradlew.bat build" and let it churn it all?
You should be able to run gradlew in subdirs, but you'll have to use a relative path to get there, i.e. within the guestbook-service module it would be "..\..\..\gradlew.bat build".
You should be able to run gradlew in subdirs, but you'll have to use a relative path to get there, i.e. within the guestbook-service module it would be "..\..\..\gradlew.bat build".
Dear David, here is the output from the complete build using "gradlew.bat build" within the guestbook-service module:
C:\dev\liferay\7.2.0-ce-ga1\ipl-workspace\mc-infocomm-ipl\modules\guestbook\guestbook-service>..\..\..\gradlew.bat build
Starting a Gradle Daemon, 3 incompatible and 1 stopped Daemons could not be reused, use --status for details> Task :modules:guestbook:guestbook-service:compileJava
C:\dev\liferay\7.2.0-ce-ga1\ipl-workspace\mc-infocomm-ipl\modules\guestbook\guestbook-service\src\main\java\mc\infocomm\ipl\test\guestbook\service\impl\GuestbookLocalServiceImpl.java:117: error: cannot find symbol
List<Entry> entries = entryLocalService.getEntries(serviceContext.getScopeGroupId(), guestbookId); // entryLocalService cannot be resolved
^
symbol: variable entryLocalService
location: class GuestbookLocalServiceImpl
C:\dev\liferay\7.2.0-ce-ga1\ipl-workspace\mc-infocomm-ipl\modules\guestbook\guestbook-service\src\main\java\mc\infocomm\ipl\test\guestbook\service\impl\GuestbookLocalServiceImpl.java:120: error: cannot find symbol
entryLocalService.deleteEntry(entry.getEntryId()); // entryLocalService cannot be resolved
^
symbol: variable entryLocalService
location: class GuestbookLocalServiceImpl
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors> Task :modules:guestbook:guestbook-service:compileJava FAILEDFAILURE: Build failed with an exception.* What went wrong:
Execution failed for task ':modules:guestbook:guestbook-service:compileJava'.
> Compilation failed; see the compiler error output for details.* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.* Get more help at https://help.gradle.orgBUILD FAILED in 11s
3 actionable tasks: 1 executed, 2 up-to-date
C:\dev\liferay\7.2.0-ce-ga1\ipl-workspace\mc-infocomm-ipl\modules\guestbook\guestbook-service>..\..\..\gradlew.bat build
Starting a Gradle Daemon, 3 incompatible and 1 stopped Daemons could not be reused, use --status for details> Task :modules:guestbook:guestbook-service:compileJava
C:\dev\liferay\7.2.0-ce-ga1\ipl-workspace\mc-infocomm-ipl\modules\guestbook\guestbook-service\src\main\java\mc\infocomm\ipl\test\guestbook\service\impl\GuestbookLocalServiceImpl.java:117: error: cannot find symbol
List<Entry> entries = entryLocalService.getEntries(serviceContext.getScopeGroupId(), guestbookId); // entryLocalService cannot be resolved
^
symbol: variable entryLocalService
location: class GuestbookLocalServiceImpl
C:\dev\liferay\7.2.0-ce-ga1\ipl-workspace\mc-infocomm-ipl\modules\guestbook\guestbook-service\src\main\java\mc\infocomm\ipl\test\guestbook\service\impl\GuestbookLocalServiceImpl.java:120: error: cannot find symbol
entryLocalService.deleteEntry(entry.getEntryId()); // entryLocalService cannot be resolved
^
symbol: variable entryLocalService
location: class GuestbookLocalServiceImpl
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors> Task :modules:guestbook:guestbook-service:compileJava FAILEDFAILURE: Build failed with an exception.* What went wrong:
Execution failed for task ':modules:guestbook:guestbook-service:compileJava'.
> Compilation failed; see the compiler error output for details.* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.* Get more help at https://help.gradle.orgBUILD FAILED in 11s
3 actionable tasks: 1 executed, 2 up-to-date
Hmm, wicked.
So I can see from the buildService output there is an Entry entity, so I'm also assuming you have an EntryLocalServiceImpl class, etc., in the mc.infocomm.ipl.test.guestbook.service.impl package?
So I can see from the buildService output there is an Entry entity, so I'm also assuming you have an EntryLocalServiceImpl class, etc., in the mc.infocomm.ipl.test.guestbook.service.impl package?
Dear David,
Of course there is an EntryLocalServiceImpl class in the mc.infocomm.ipl.test.guestbook.service.impl package.
It is the one with inside the Entry's methods that are not found from the GuestbookLocalServiceImpl class.
I can't call the methods entryLocalService.getEntries() and entryLocalService.deleteEntry().
Here is the code:
package mc.infocomm.ipl.test.guestbook.service.impl;import com.liferay.portal.aop.AopService;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.util.OrderByComparator;
import com.liferay.portal.kernel.util.Validator;import java.util.Date;
import java.util.List;import mc.infocomm.ipl.test.guestbook.model.Entry;
import mc.infocomm.ipl.test.guestbook.service.base.EntryLocalServiceBaseImpl;
import mc.infocomm.ipl.test.guestbook.exception.EntryEmailException;
import mc.infocomm.ipl.test.guestbook.exception.EntryMessageException;
import mc.infocomm.ipl.test.guestbook.exception.EntryNameException;import org.osgi.service.component.annotations.Component;/**
* The implementation of the entry local service.
*
* <p>
* All custom service methods should be put in this class. Whenever methods are added, rerun ServiceBuilder to copy their definitions into the <code>mc.infocomm.ipl.test.guestbook.service.EntryLocalService</code> interface.
*
* <p>
* This is a local service. Methods of this service will not have security checks based on the propagated JAAS credentials because this service can only be accessed from within the same VM.
* </p>
*
* @author icarrara
* @see EntryLocalServiceBaseImpl
*/
@Component(
property = "model.class.name=mc.infocomm.ipl.test.guestbook.model.Entry",
service = AopService.class
)
public class EntryLocalServiceImpl extends EntryLocalServiceBaseImpl { /*
* NOTE FOR DEVELOPERS:
*
* Never reference this class directly. Use <code>mc.infocomm.ipl.test.guestbook.service.EntryLocalService</code> via injection or a <code>org.osgi.util.tracker.ServiceTracker</code> or use <code>mc.infocomm.ipl.test.guestbook.service.EntryLocalServiceUtil</code>.
*/
public Entry addEntry(long userId, long guestbookId, String name, String email, String message, ServiceContext serviceContext) throws PortalException { long groupId = serviceContext.getScopeGroupId(); User user = userLocalService.getUserById(userId); Date now = new Date(); validate(name, email, message); long entryId = counterLocalService.increment(); Entry entry = entryPersistence.create(entryId); entry.setUuid(serviceContext.getUuid());
entry.setUserId(userId);
entry.setGroupId(groupId);
entry.setCompanyId(user.getCompanyId());
entry.setUserName(user.getFullName());
entry.setCreateDate(serviceContext.getCreateDate(now));
entry.setModifiedDate(serviceContext.getModifiedDate(now));
entry.setExpandoBridgeAttributes(serviceContext);
entry.setGuestbookId(guestbookId);
entry.setName(name);
entry.setEmail(email);
entry.setMessage(message); entryPersistence.update(entry); return entry;
}
public Entry updateEntry (long userId, long guestbookId, long entryId, String name, String email, String message, ServiceContext serviceContext) throws PortalException, SystemException {
Date now = new Date();
validate(name, email, message);
Entry entry = getEntry(entryId);
User user = userLocalService.getUserById(userId);
entry.setUserId(userId);
entry.setUserName(user.getFullName());
entry.setModifiedDate(serviceContext.getModifiedDate(now));
entry.setName(name);
entry.setEmail(email);
entry.setMessage(message);
entry.setExpandoBridgeAttributes(serviceContext);
entryPersistence.update(entry);
return entry;
}
public Entry deleteEntry (long entryId, ServiceContext serviceContext) throws PortalException {
Entry entry = getEntry(entryId); entry = deleteEntry(entryId); return entry;
}
public List<Entry> getEntries(long groupId, long guestbookId) {
return entryPersistence.findByG_G(groupId, guestbookId);
}
public List<Entry> getEntries(long groupId, long guestbookId, int start, int end) throws SystemException { return entryPersistence.findByG_G(groupId, guestbookId, start, end);
}
public List<Entry> getEntries(
long groupId, long guestbookId, int start, int end, OrderByComparator<Entry> obc) { return entryPersistence.findByG_G(groupId, guestbookId, start, end, obc);
}
public int getEntriesCount(long groupId, long guestbookId) {
return entryPersistence.countByG_G(groupId, guestbookId);
}
protected void validate(String name, String email, String entry) throws PortalException { if (Validator.isNull(name)) {
throw new EntryNameException();
} if (!Validator.isEmailAddress(email)) {
throw new EntryEmailException();
} if (Validator.isNull(entry)) {
throw new EntryMessageException();
}
}
}
Of course there is an EntryLocalServiceImpl class in the mc.infocomm.ipl.test.guestbook.service.impl package.
It is the one with inside the Entry's methods that are not found from the GuestbookLocalServiceImpl class.
I can't call the methods entryLocalService.getEntries() and entryLocalService.deleteEntry().
Here is the code:
package mc.infocomm.ipl.test.guestbook.service.impl;import com.liferay.portal.aop.AopService;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.util.OrderByComparator;
import com.liferay.portal.kernel.util.Validator;import java.util.Date;
import java.util.List;import mc.infocomm.ipl.test.guestbook.model.Entry;
import mc.infocomm.ipl.test.guestbook.service.base.EntryLocalServiceBaseImpl;
import mc.infocomm.ipl.test.guestbook.exception.EntryEmailException;
import mc.infocomm.ipl.test.guestbook.exception.EntryMessageException;
import mc.infocomm.ipl.test.guestbook.exception.EntryNameException;import org.osgi.service.component.annotations.Component;/**
* The implementation of the entry local service.
*
* <p>
* All custom service methods should be put in this class. Whenever methods are added, rerun ServiceBuilder to copy their definitions into the <code>mc.infocomm.ipl.test.guestbook.service.EntryLocalService</code> interface.
*
* <p>
* This is a local service. Methods of this service will not have security checks based on the propagated JAAS credentials because this service can only be accessed from within the same VM.
* </p>
*
* @author icarrara
* @see EntryLocalServiceBaseImpl
*/
@Component(
property = "model.class.name=mc.infocomm.ipl.test.guestbook.model.Entry",
service = AopService.class
)
public class EntryLocalServiceImpl extends EntryLocalServiceBaseImpl { /*
* NOTE FOR DEVELOPERS:
*
* Never reference this class directly. Use <code>mc.infocomm.ipl.test.guestbook.service.EntryLocalService</code> via injection or a <code>org.osgi.util.tracker.ServiceTracker</code> or use <code>mc.infocomm.ipl.test.guestbook.service.EntryLocalServiceUtil</code>.
*/
public Entry addEntry(long userId, long guestbookId, String name, String email, String message, ServiceContext serviceContext) throws PortalException { long groupId = serviceContext.getScopeGroupId(); User user = userLocalService.getUserById(userId); Date now = new Date(); validate(name, email, message); long entryId = counterLocalService.increment(); Entry entry = entryPersistence.create(entryId); entry.setUuid(serviceContext.getUuid());
entry.setUserId(userId);
entry.setGroupId(groupId);
entry.setCompanyId(user.getCompanyId());
entry.setUserName(user.getFullName());
entry.setCreateDate(serviceContext.getCreateDate(now));
entry.setModifiedDate(serviceContext.getModifiedDate(now));
entry.setExpandoBridgeAttributes(serviceContext);
entry.setGuestbookId(guestbookId);
entry.setName(name);
entry.setEmail(email);
entry.setMessage(message); entryPersistence.update(entry); return entry;
}
public Entry updateEntry (long userId, long guestbookId, long entryId, String name, String email, String message, ServiceContext serviceContext) throws PortalException, SystemException {
Date now = new Date();
validate(name, email, message);
Entry entry = getEntry(entryId);
User user = userLocalService.getUserById(userId);
entry.setUserId(userId);
entry.setUserName(user.getFullName());
entry.setModifiedDate(serviceContext.getModifiedDate(now));
entry.setName(name);
entry.setEmail(email);
entry.setMessage(message);
entry.setExpandoBridgeAttributes(serviceContext);
entryPersistence.update(entry);
return entry;
}
public Entry deleteEntry (long entryId, ServiceContext serviceContext) throws PortalException {
Entry entry = getEntry(entryId); entry = deleteEntry(entryId); return entry;
}
public List<Entry> getEntries(long groupId, long guestbookId) {
return entryPersistence.findByG_G(groupId, guestbookId);
}
public List<Entry> getEntries(long groupId, long guestbookId, int start, int end) throws SystemException { return entryPersistence.findByG_G(groupId, guestbookId, start, end);
}
public List<Entry> getEntries(
long groupId, long guestbookId, int start, int end, OrderByComparator<Entry> obc) { return entryPersistence.findByG_G(groupId, guestbookId, start, end, obc);
}
public int getEntriesCount(long groupId, long guestbookId) {
return entryPersistence.countByG_G(groupId, guestbookId);
}
protected void validate(String name, String email, String entry) throws PortalException { if (Validator.isNull(name)) {
throw new EntryNameException();
} if (!Validator.isEmailAddress(email)) {
throw new EntryEmailException();
} if (Validator.isNull(entry)) {
throw new EntryMessageException();
}
}
}
Ah, I have an inkling having seen the 7.2 syntax...
Can you try adding the following to your bnd.bnd file in the guestbook-service module:
Can you try adding the following to your bnd.bnd file in the guestbook-service module:
-dsannotations-options: inherit
Okay, Ivano, I have to start with an apology...
I was assuming that the long-standing practice of Service Builder injecting local service and persistence automatically in the XXXLocalServiceImpl's super class would obviously not have been stripped, even for 7.2.
But in discussions w/ other Liferay folks I've learned that actually has happened. Other local services and persistence instances for entities in the same service.xml file are no longer automatically injected.
Mostly this was due to the conversion of the local services into pure OSGi components and the issues that would have sprung from having circular references on all of the local service implementations (if Guestbook @References the Entry local service and Entry @References the Guestbook local service, neither one can be resolved by OSGi since all references are not ready for injection).
Instead, that whole practice has been scrapped.
Going forward, if you need other local service or persistence instances for the other entities, you need to manually declare the member variables yourself and @Reference inject them. Note, however, that by doing this yourself it doesn't eliminate the potential of creating a circular reference in your components that would prevent them from starting.
I'm going to hook up w/ the documentation team and other folks involved to get clarification about how developers should proceed and certainly update the doco to represent these new developer responsibilities.
I'm just sorry it took this long to develop the proper answer for you...
I was assuming that the long-standing practice of Service Builder injecting local service and persistence automatically in the XXXLocalServiceImpl's super class would obviously not have been stripped, even for 7.2.
But in discussions w/ other Liferay folks I've learned that actually has happened. Other local services and persistence instances for entities in the same service.xml file are no longer automatically injected.
Mostly this was due to the conversion of the local services into pure OSGi components and the issues that would have sprung from having circular references on all of the local service implementations (if Guestbook @References the Entry local service and Entry @References the Guestbook local service, neither one can be resolved by OSGi since all references are not ready for injection).
Instead, that whole practice has been scrapped.
Going forward, if you need other local service or persistence instances for the other entities, you need to manually declare the member variables yourself and @Reference inject them. Note, however, that by doing this yourself it doesn't eliminate the potential of creating a circular reference in your components that would prevent them from starting.
I'm going to hook up w/ the documentation team and other folks involved to get clarification about how developers should proceed and certainly update the doco to represent these new developer responsibilities.
I'm just sorry it took this long to develop the proper answer for you...
Dear David,
No apologies from you, you are teaching me many new things.
Thank you for your last reply about the @Reference annotation.
Unfortunately I can't understand where I have to put the above annotation.
Also I read your Blog article here https://liferay.dev/blogs/-/blogs/liferay-osgi-annotations-what-they-are-and-when-to-use-them but still I'm not able to call methods in EntryLocalServiceImpl class from the GuestbookLocalServiceImpl class in my Guestbook application in 7.2 environment.
Please could you address me where I have to put the @Reference annotation in my services ?
Thank you in advance,
Ivano C.
No apologies from you, you are teaching me many new things.
Thank you for your last reply about the @Reference annotation.
Unfortunately I can't understand where I have to put the above annotation.
Also I read your Blog article here https://liferay.dev/blogs/-/blogs/liferay-osgi-annotations-what-they-are-and-when-to-use-them but still I'm not able to call methods in EntryLocalServiceImpl class from the GuestbookLocalServiceImpl class in my Guestbook application in 7.2 environment.
Please could you address me where I have to put the @Reference annotation in my services ?
Thank you in advance,
Ivano C.
Dear David, probably I solved my case :-)
I added the below code in the GuestbookLocalServiceImpl class:
@Reference(unbind = "-")
protected void setEntryService(EntryLocalService entryLocalService) {
_entryLocalService = entryLocalService;
} private EntryLocalService _entryLocalService;
Then I changed the calls to the methods provided by the EntryLocalServiceImpl class, for example:
List<Entry> entries = _entryLocalService.getEntries(serviceContext.getScopeGroupId(), guestbookId); // NO MORE ERRORS !!!
It is the above the right solution ?
Thank you,
Ivvano C.
I added the below code in the GuestbookLocalServiceImpl class:
@Reference(unbind = "-")
protected void setEntryService(EntryLocalService entryLocalService) {
_entryLocalService = entryLocalService;
} private EntryLocalService _entryLocalService;
Then I changed the calls to the methods provided by the EntryLocalServiceImpl class, for example:
List<Entry> entries = _entryLocalService.getEntries(serviceContext.getScopeGroupId(), guestbookId); // NO MORE ERRORS !!!
It is the above the right solution ?
Thank you,
Ivvano C.
Yep, that's spot on...
Alternatively, you could set the dependency injector back to spring to make things work the way they used to.
I wrote up a blog about SB 7.2 changes, some of which I learned about when helping here: https://liferay.dev/blogs/-/blogs/important-7-2-service-builder-changes
Alternatively, you could set the dependency injector back to spring to make things work the way they used to.
I wrote up a blog about SB 7.2 changes, some of which I learned about when helping here: https://liferay.dev/blogs/-/blogs/important-7-2-service-builder-changes
Ok, I added "dependency-injector='spring'" in the service.xml file.
After I removed the below code in the GuestbookLocalServiceImpl class:
@Reference(unbind = "-")
protected void setEntryService(EntryLocalService entryLocalService) {
_entryLocalService = entryLocalService;
}
private EntryLocalService _entryLocalService;
Then I changed the calls to the methods provided by the EntryLocalServiceImpl class, for example:
List<Entry> entries = entryLocalService.getEntries(serviceContext.getScopeGroupId(), guestbookId); // NO MORE ERRORS !!!
But at that point I get a lot of errors in the service packages saying: "The import com.liferay.portal.spring cannot be resolved".
I solved the issue adding the below in the build.gradle:
compile 'com.liferay:com.liferay.portal.spring.extender:2.0.15'.
BUT now in the IDE when I drag the guestbook-service module in the Tomcat bundle the module doesn't start and is marked with a red point.
If I do a deploy Gradle task I get the below error log:
Gradle Tasks: deploy> Task :modules:guestbook:guestbook-api:compileJava UP-TO-DATE
> Task :modules:guestbook:guestbook-api:buildCSS NO-SOURCE
> Task :modules:guestbook:guestbook-api:processResources NO-SOURCE
> Task :modules:guestbook:guestbook-api:transpileJS SKIPPED
> Task :modules:guestbook:guestbook-api:configJSModules SKIPPED
> Task :modules:guestbook:guestbook-api:replaceSoyTranslation NO-SOURCE
> Task :modules:guestbook:guestbook-api:wrapSoyAlloyTemplate SKIPPED
> Task :modules:guestbook:guestbook-api:classes UP-TO-DATE
> Task :modules:guestbook:guestbook-api:jar UP-TO-DATE
> Task :modules:guestbook:guestbook-service:compileJava UP-TO-DATE
> Task :modules:guestbook:guestbook-service:buildCSS NO-SOURCE
> Task :modules:guestbook:guestbook-service:processResources UP-TO-DATE
> Task :modules:guestbook:guestbook-service:transpileJS SKIPPED
> Task :modules:guestbook:guestbook-service:configJSModules SKIPPED
> Task :modules:guestbook:guestbook-service:replaceSoyTranslation NO-SOURCE
> Task :modules:guestbook:guestbook-service:wrapSoyAlloyTemplate SKIPPED
> Task :modules:guestbook:guestbook-service:classes UP-TO-DATE> Task :modules:guestbook:guestbook-service:jar FAILED
error : Class mc.infocomm.ipl.test.guestbook.service.impl.EntryLocalServiceImpl is not assignable to specified service com.liferay.portal.aop.AopService
error : Class mc.infocomm.ipl.test.guestbook.service.impl.EntryServiceImpl is not assignable to specified service com.liferay.portal.aop.AopService
error : Class mc.infocomm.ipl.test.guestbook.service.impl.GuestbookLocalServiceImpl is not assignable to specified service com.liferay.portal.aop.AopService
error : Class mc.infocomm.ipl.test.guestbook.service.impl.GuestbookServiceImpl is not assignable to specified service com.liferay.portal.aop.AopServiceFAILURE: Build failed with an exception.* What went wrong:
Execution failed for task ':modules:guestbook:guestbook-service:jar'.
> Bundle mc.infocomm.ipl.test.guestbook.service-1.0.0.jar has errors
At this point I'm a bit worried about the absence of a some sort of guideline about dependencies to develop in 7.x versions.
Thank you in advance for any other help,
Ivano C.
After I removed the below code in the GuestbookLocalServiceImpl class:
@Reference(unbind = "-")
protected void setEntryService(EntryLocalService entryLocalService) {
_entryLocalService = entryLocalService;
}
private EntryLocalService _entryLocalService;
Then I changed the calls to the methods provided by the EntryLocalServiceImpl class, for example:
List<Entry> entries = entryLocalService.getEntries(serviceContext.getScopeGroupId(), guestbookId); // NO MORE ERRORS !!!
But at that point I get a lot of errors in the service packages saying: "The import com.liferay.portal.spring cannot be resolved".
I solved the issue adding the below in the build.gradle:
compile 'com.liferay:com.liferay.portal.spring.extender:2.0.15'.
BUT now in the IDE when I drag the guestbook-service module in the Tomcat bundle the module doesn't start and is marked with a red point.
If I do a deploy Gradle task I get the below error log:
Gradle Tasks: deploy> Task :modules:guestbook:guestbook-api:compileJava UP-TO-DATE
> Task :modules:guestbook:guestbook-api:buildCSS NO-SOURCE
> Task :modules:guestbook:guestbook-api:processResources NO-SOURCE
> Task :modules:guestbook:guestbook-api:transpileJS SKIPPED
> Task :modules:guestbook:guestbook-api:configJSModules SKIPPED
> Task :modules:guestbook:guestbook-api:replaceSoyTranslation NO-SOURCE
> Task :modules:guestbook:guestbook-api:wrapSoyAlloyTemplate SKIPPED
> Task :modules:guestbook:guestbook-api:classes UP-TO-DATE
> Task :modules:guestbook:guestbook-api:jar UP-TO-DATE
> Task :modules:guestbook:guestbook-service:compileJava UP-TO-DATE
> Task :modules:guestbook:guestbook-service:buildCSS NO-SOURCE
> Task :modules:guestbook:guestbook-service:processResources UP-TO-DATE
> Task :modules:guestbook:guestbook-service:transpileJS SKIPPED
> Task :modules:guestbook:guestbook-service:configJSModules SKIPPED
> Task :modules:guestbook:guestbook-service:replaceSoyTranslation NO-SOURCE
> Task :modules:guestbook:guestbook-service:wrapSoyAlloyTemplate SKIPPED
> Task :modules:guestbook:guestbook-service:classes UP-TO-DATE> Task :modules:guestbook:guestbook-service:jar FAILED
error : Class mc.infocomm.ipl.test.guestbook.service.impl.EntryLocalServiceImpl is not assignable to specified service com.liferay.portal.aop.AopService
error : Class mc.infocomm.ipl.test.guestbook.service.impl.EntryServiceImpl is not assignable to specified service com.liferay.portal.aop.AopService
error : Class mc.infocomm.ipl.test.guestbook.service.impl.GuestbookLocalServiceImpl is not assignable to specified service com.liferay.portal.aop.AopService
error : Class mc.infocomm.ipl.test.guestbook.service.impl.GuestbookServiceImpl is not assignable to specified service com.liferay.portal.aop.AopServiceFAILURE: Build failed with an exception.* What went wrong:
Execution failed for task ':modules:guestbook:guestbook-service:jar'.
> Bundle mc.infocomm.ipl.test.guestbook.service-1.0.0.jar has errors
At this point I'm a bit worried about the absence of a some sort of guideline about dependencies to develop in 7.x versions.
Thank you in advance for any other help,
Ivano C.
It wouldn't surprise me if the environment is now confused, first version of API was based on OSGi, this one based on Spring...
I would recommend purging Guestbook from the env completely (make sure there is nothing in osgi/modules, work, etc) as well as purging osgi/state.
Also, for spring DI none of your classes should be declared as @Components. You'll want to purge all of these annotations. It may be necessary, although I admit I don't know, to try purging all of the generated SB code and then re-gen again, as this would help to eliminate any possible code hanging around that was based off of the other dependency injector.
This kind of cleanup has never been easy in SB, relatively simple things like changing package name in the service.xml would often leave cruft hanging behind... It just takes a little bit of patience to work through it...
I would recommend purging Guestbook from the env completely (make sure there is nothing in osgi/modules, work, etc) as well as purging osgi/state.
Also, for spring DI none of your classes should be declared as @Components. You'll want to purge all of these annotations. It may be necessary, although I admit I don't know, to try purging all of the generated SB code and then re-gen again, as this would help to eliminate any possible code hanging around that was based off of the other dependency injector.
This kind of cleanup has never been easy in SB, relatively simple things like changing package name in the service.xml would often leave cruft hanging behind... It just takes a little bit of patience to work through it...
Dear David,
Thank you very much for your efforts during the development of this thread.
In fact other than resolve the issue, you teached me a lot of things and helped me to follow my learning curve.
Contrarily to your final advise in the final chapter "Choosing The Right Dependency Injector" in the https://liferay.dev/blogs/-/blogs/important-7-2-service-builder-changes Blog article, I decided to use the new default in Service Builder that is dependency-injector="ds"
The above cause starting a new project based on 7.2 I think that if Liferay made the choice of the above as the new Service Builder default, it can be a better guarantee of continuity for the future.
Best regards and thank you again for your help!
Ivano C.
Thank you very much for your efforts during the development of this thread.
In fact other than resolve the issue, you teached me a lot of things and helped me to follow my learning curve.
Contrarily to your final advise in the final chapter "Choosing The Right Dependency Injector" in the https://liferay.dev/blogs/-/blogs/important-7-2-service-builder-changes Blog article, I decided to use the new default in Service Builder that is dependency-injector="ds"
The above cause starting a new project based on 7.2 I think that if Liferay made the choice of the above as the new Service Builder default, it can be a better guarantee of continuity for the future.
Best regards and thank you again for your help!
Ivano C.
You're welcome, Ivano.
I think choosing the right dependency-injector is going to be a personal choice. I also don't believe it has to be a "forever" choice; I think it is perfectly acceptable to choose "spring" for one SB implementation and "ds" for another. Use the one that best fits what you are building.
Me, most of the time I tend to see all of my entities in the service.xml as "tightly coupled", such as the guestbook and entry entities. Since they are coupled, for me at least, I feel like guestbook methods (like the delete example) will be invoking entry methods and entry methods will at times want to invoke guestbook methods (i.e. if guestbook had a "last entry timestamp" that was updated every time an entry were being added). Because I see these kinds of relationships as being a "default state" for the entities, I want them to establish and use the services and persistence layers of others and I wouldn't want to have to figure out how to work around circular dependencies, etc. So for me, a "spring" dependency injector is typically going to be the right choice because of how I see the entities relating.
The DS option is definitely easier when your service components need to access other DS components beyond the local service.xml services, so if I knew I had to go down that road, DS would probably be my choice.
I don't think there's ever going to be a "right" vs "wrong" answer, you can make both options fit in pretty much every case you find.
I wrote the blog, though, because I really wasn't aware of these changes for 7.2, and it wouldn't surprise me if others who had been doing Liferay for a while didn't know about them either. Yours is the second error about the new 7.2 implementation I've encountered, so I wanted to make sense out of what was going on and spell everything out to avoid future devs from stumbling into the same situation.
I think choosing the right dependency-injector is going to be a personal choice. I also don't believe it has to be a "forever" choice; I think it is perfectly acceptable to choose "spring" for one SB implementation and "ds" for another. Use the one that best fits what you are building.
Me, most of the time I tend to see all of my entities in the service.xml as "tightly coupled", such as the guestbook and entry entities. Since they are coupled, for me at least, I feel like guestbook methods (like the delete example) will be invoking entry methods and entry methods will at times want to invoke guestbook methods (i.e. if guestbook had a "last entry timestamp" that was updated every time an entry were being added). Because I see these kinds of relationships as being a "default state" for the entities, I want them to establish and use the services and persistence layers of others and I wouldn't want to have to figure out how to work around circular dependencies, etc. So for me, a "spring" dependency injector is typically going to be the right choice because of how I see the entities relating.
The DS option is definitely easier when your service components need to access other DS components beyond the local service.xml services, so if I knew I had to go down that road, DS would probably be my choice.
I don't think there's ever going to be a "right" vs "wrong" answer, you can make both options fit in pretty much every case you find.
I wrote the blog, though, because I really wasn't aware of these changes for 7.2, and it wouldn't surprise me if others who had been doing Liferay for a while didn't know about them either. Yours is the second error about the new 7.2 implementation I've encountered, so I wanted to make sense out of what was going on and spell everything out to avoid future devs from stumbling into the same situation.
Dear David,
One more question ...
Since I decided to use the dependency-injector="ds", now I have a doubt.
In a previous message you wrote: "Also, for spring DI none of your classes should be declared as @Components. You'll want to purge all of these annotations."
When I ran Service Builder the first time, with the dependency-injector="ds" as default, it generated the below code in the skeleton of all *LocalServiceImpl classes:
@Component(
property = "model.class.name=mc.infocomm.ipl.test.guestbook.model.Guestbook",
service = AopService.class
)
public class GuestbookLocalServiceImpl extends GuestbookLocalServiceBaseImpl {
}
So now I have to remove the above code from all *LocalServiceImpl classes ?
Please note that actually the Guestbook portlet including the @Component annotations in all *LocalServiceImpl classes is running very well and without errors.
Thank you again for clarifications and help.
Ivano C.
One more question ...
Since I decided to use the dependency-injector="ds", now I have a doubt.
In a previous message you wrote: "Also, for spring DI none of your classes should be declared as @Components. You'll want to purge all of these annotations."
When I ran Service Builder the first time, with the dependency-injector="ds" as default, it generated the below code in the skeleton of all *LocalServiceImpl classes:
@Component(
property = "model.class.name=mc.infocomm.ipl.test.guestbook.model.Guestbook",
service = AopService.class
)
public class GuestbookLocalServiceImpl extends GuestbookLocalServiceBaseImpl {
}
So now I have to remove the above code from all *LocalServiceImpl classes ?
Please note that actually the Guestbook portlet including the @Component annotations in all *LocalServiceImpl classes is running very well and without errors.
Thank you again for clarifications and help.
Ivano C.
Sorry for the confusion, Ivano.
If you are using "spring" for the dependency injector, then your local service impl classes should not have the @Component annotation nor @Reference injection inside of the class. The local service impl will be a Spring bean, not a DS component.
If you are using "ds" for the dependency injector, then your local service impl classes must have the @Component annotation in order to be exposed as a DS component and are free to use @Reference injection.
The bodies of the local service impl class shouldn't change much between the two dependency injectors; if you have an addGuestbook(...) method, it would apply to both forms so you don't need to strip it out when switching.
The thing to remember is that historically Service Builder has been really bad at cleaning up after itself. I don't know that SB can clean up correctly when you switch the dependency injector after you have built the services the first time. My guess is it doesn't know how to clean up at all, leaving you the developer with the responsibility to perform the necessary cleanup.
If you are using "spring" for the dependency injector, then your local service impl classes should not have the @Component annotation nor @Reference injection inside of the class. The local service impl will be a Spring bean, not a DS component.
If you are using "ds" for the dependency injector, then your local service impl classes must have the @Component annotation in order to be exposed as a DS component and are free to use @Reference injection.
The bodies of the local service impl class shouldn't change much between the two dependency injectors; if you have an addGuestbook(...) method, it would apply to both forms so you don't need to strip it out when switching.
The thing to remember is that historically Service Builder has been really bad at cleaning up after itself. I don't know that SB can clean up correctly when you switch the dependency injector after you have built the services the first time. My guess is it doesn't know how to clean up at all, leaving you the developer with the responsibility to perform the necessary cleanup.
Copyright © 2025 Liferay, Inc
• Privacy Policy
Powered by Liferay™