0

How do I fetch Liferay's entity using DynamicQuery or Finder class?

  • Asked - Mar 11, 2011, 03:17 PM
    / Viewed 28800 Times
    Hi,

    My organization structure is simple: one company, one root organisation and many level of organization and location under the root organization.

    In my custom portlet, I needed to query the organization table to fetch the list of all my company's organizations (child and sub childs (location included) ) except the root organization. So I created this query:

    public static List<organization> getOrganizations(boolean withLocations) {
                DynamicQuery query = DynamicQueryFactoryUtil
                            .forClass(Organization.class)
                            .add(PropertyFactoryUtil.forName("companyId").eq(companyId))
                            .add(PropertyFactoryUtil.forName("organizationId").ne(orgId));
                try {
                      return (List<organization>) OrganizationLocalServiceUtil
                                 .dynamicQuery(query, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
                } catch (SystemException e) {
                      return new ArrayList<organization>();
                }
          }
    </organization></organization></organization>

    I got the following stack trace
    14:44:17,505 ERROR [DynamicQueryFactoryImpl:83] Unable find model com.liferay.portal.model.impl.OrganizationImpl
    java.lang.ClassNotFoundException: com.liferay.portal.model.impl.OrganizationImpl
          at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1516)
          at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1361)
          at com.liferay.portal.dao.orm.hibernate.DynamicQueryFactoryImpl.getImplClass(DynamicQueryFactoryImpl.java:78)
          at com.liferay.portal.dao.orm.hibernate.DynamicQueryFactoryImpl.getImplClass(DynamicQueryFactoryImpl.java:59)
          at com.liferay.portal.dao.orm.hibernate.DynamicQueryFactoryImpl.forClass(DynamicQueryFactoryImpl.java:33)
          at com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil.forClass(DynamicQueryFactoryUtil.java:23)
          at com.acq.portlet.common.util.AcqOrganizationUtil.getOrganizations(AcqOrganizationUtil.java:44)
          at org.apache.jsp.pages.project.cp.edit.plans_005fprints_jsp._jspService(plans_005fprints_jsp.java:456)
          at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
          at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)
          at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
          at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    


    The inherent problem here is that I can't query any of Liferay entity without having the jar portal-impl.jar in either my portlet webapp or in the global class path.

    Both of these solution are not recommended.

    So how can I create custom queries (using finder class or DynamicQuery) to fetch data in one of Liferay's table ?

    How would one go about to fetching the list of user that are associated with his Portlet's entities ? Is the best one could do is return the list of userId and then fetch them one by one ?

    Is putting the portal-impl.jar file (currently found in tomcat/ROOT/WEB-INF/lib) in the global classpath a nessecary 'evil' ?

    Thanks to all, any input on this would be appreciated.
    cheers,
    Charles

    1 Answers

    0
    Answered - Mar 11, 2011, 05:55 PM
    (Edited)
    Hy Charles,

    You should be fine doing this:
    DynamicQueryFactoryUtil.forName(Organization.class, PortalClassLoaderUtil.getClassLoader());
    Replied - Mar 11, 2011, 07:33 PM
    (Edited)
    Hi Thiago,

    Great it worked

    No to be picky but it's "forClass(..)" and not "forName(..)" (in liferay 6.0.5)
    DynamicQuery query = DynamicQueryFactoryUtil
                            .forClass(Organization.class,
                                       PortalClassLoaderUtil.getClassLoader())
                            .add(PropertyFactoryUtil.forName("companyId").eq(companyId))
                            .add(PropertyFactoryUtil.forName("organizationId").ne(orgId));
    

    But it worked. emoticon

    How would I do it in a FinderImpl class. Here I have a method that should return a list of DLFileEntry.
    public List<dlfileentry> findFilesByProject(long projectId) throws SystemException {
    
    		String sql = CustomSQLUtil.get(FIND_BY_PROJECT);
    		Session session = null;
    		try {
    			session = openSession();
    
    			SQLQuery q = session.createSQLQuery(sql);
    
    			q.addEntity("DLFileEntry", DLFileEntry.class);
    
    			QueryPos qPos = QueryPos.getInstance(q);
    
    			qPos.add(projectId);
    
    			@SuppressWarnings("unchecked")
    			List<dlfileentry> list= (List<dlfileentry>) QueryUtil.list(q, getDialect(),
    					QueryUtil.ALL_POS, QueryUtil.ALL_POS);
    
    			return list;
    
    		} catch (Exception e) {
    			throw new SystemException(e);
    		} finally {
    			closeSession(session);
    		}
    	}</dlfileentry></dlfileentry></dlfileentry>


    The line « q.addEntity("DLFileEntry", DLFileEntry.class); » will not work ( neither will « q.addEntity("DLFileEntry", DLFileEntryImpl.class); » ) and give a similar exception « Unable find model com.liferay.portal.model.impl.DLFileEntryImpl ».

    How do I pass the impl class to the method addEntity ?

    thanks
    cheers.
    Replied - Mar 11, 2011, 07:46 PM
    (Edited)
    Humm, sorry about my mistake.

    I'm not sure if you will be able to invoke q.addEntity("DLFileEntry", DLFileEntry.class); on classes from portal-impl.jar. I think you need to covert this code to a DynamicQuery based code.
    Replied - Mar 11, 2011, 08:02 PM
    (Edited)
    To bad for that.

    Still, thanks for the help, greatly appreciated.

    Cheers
    Replied - May 29, 2011, 05:06 PM
    (Edited)
    Hi Guys,

    I was using the DynamicQuery but was getting the error 'Unable find model [XYZ]'. Was trying to find the issue behind the same and found the error was from
    DynamicQueryFactoryImpl.java --> getImplClass().

    I resolved the same and thought of sharing the same...
    To allow your DynamicQuery to access the implementation class:
    1) The Implementation class is in your portlet:
    Don´t use a special classloader - it will work out of the box.

    2) The Implementation class is part of the portal (Like User, Role or Group)
    Use the following:
    Classloader loader = PortalClassLoaderUtil.getClassLoader());

    3) The implementation class is in another portlet.
    Use the following:
    ClassLoader classLoader = (ClassLoader)PortletBeanLocatorUtil.locate(ClpSerializer.SERVLET_CONTEXT_NAME,"portletClassLoader");

    Thanks,
    Replied - Sep 28, 2011, 02:15 PM
    (Edited)
    Hi,

    If the implementation class is part of the portal, but it was overwritten in an ext plugin I suppose I am in the 3rd case. (Anyway, none of the first two are working).
    If so, what does ClpSerializer mean, and how should I import it?

    Thanks
    Replied - Sep 28, 2011, 04:59 PM
    (Edited)
    Hey Thiago, You can actually, Just look at my example in http://www.liferay.com/community/forums/-/message_boards/message/7158040
    Replied - Sep 28, 2011, 05:05 PM
    (Edited)
    When you share a service between two portlets you place the service.jar of one portlet in another portlet. One of the classes included in this service.jar is ClpSerializer. What it does is irrelevant in this case, just know that it has a static string defined on it that is the name of the servlet context of the portlet that holds the implementation of the service. If you can't find it you need to add the service.jar to your classpath