This website uses cookies to ensure you get the best experience. Learn More.
Hooks revisited (6) - create a custom finder
Define a finder interface as follows:
public interface CustomAssetEntryQueryFinder {
public List<AssetEntry> findEntries(
CustomAssetEntryQueryWrapper customEntryQuery)
throws SystemException;
}
Subsequently create an implementation of the interface:
public class CustomAssetEntryQueryFinderImpl
extends BasePersistenceImpl<CustomAssetEntryQuery>
implements CustomAssetEntryQueryFinder {
...
@Override
CustomAssetEntryQueryWrapper entryQuery)
As a template for the custom finder class we can use the unmodified source of the framework's finder implementation class AssetEntryFinderImpl. Actually we will need to integrate an additional, however optional, SQL fragment into the existing code. The finder method will look something like this:
throws SystemException {
// fetch liferay's session factory
SessionFactory sessionFactory =
(SessionFactory)PortalBeanLocatorUtil.locate("liferaySessionFactory");
Session session = null;
try {
// open session using liferay's session factory
session = sessionFactory.openSession();
SQLQuery q = buildAssetQuerySQL(
entryQuery, false, session);
return (List<AssetEntry>)QueryUtil.list(
q, getDialect(),
entryQuery.getStart(),
entryQuery.getEnd());
catch (Exception e) {
throw new SystemException(e);
finally {
closeSession(session);
Please note that the custom finder implementation will be loaded by the plug-in context loader due to the simple fact that, in contrast with the access service classes, it will be part of the plug-in package war. The framework's original finder, on the other hand, is loaded by the portal's context loader. This difference must be reflected in the coding. We need the portal's SessionFactory to create the database session because the referenced core tables are not known for the plug-in's default SessionFactory. Similarly, we need to access the portal properties through the PropsUtil class instead of accessing them directly as in the original finder implementation. However, these are only minor technical differences; the custom finder implementation will still remain very close to the template.
The complete SQL statement will be compiled from all the search criteria supplied by the entryQuery argument of the method:
protected SQLQuery buildAssetQuerySQL(
CustomAssetEntryQueryWrapper entryQuery,
Session session)
// append join condition
if (entryQuery.getAuthorName().length() > 0) {
sb.append("INNER JOIN ");
sb.append("User_ ON ");
sb.append("(AssetEntry.userID = User_.userId) ");
// append where condition
sb.append(" AND (User_.screenname = ?)");
// set positional bind variable
qpos.add(enryQuery.getAuthorName());
We need to regenerate the implementation part of the plug-in in order to add the finder to the entity. This works like a charm thanks to the Service Builder and our effort of splitting the build job into several build targets. Thus we were able to fulfill requirement d).