Get PortletPreferences

No Comments »

import javax.portlet.PortletPreferences;
import com.liferay.portlet.PortletPreferencesFactoryUtil;

PortletPreferences portletSetup = PortletPreferencesFactoryUtil.getLayoutPortletSetup( layout , portletId); 
String foo = portletSetup.getValue("foo", "defaultValue");

Get all portlets placed on a page (layout)

No Comments »

To get all portlets placed on a page (layout) you can use the following lines of code:

import com.liferay.portal.model.LayoutTypePortlet;
import com.liferay.portal.model.Portlet;

LayoutTypePortlet layoutTypePortlet = (LayoutTypePortlet) l.getLayoutType();
List< Portlet > portlets = layoutTypePortlet.getAllPortlets();

Liferay WebServices

No Comments »

Liferay offers the potential to use it's services via WebServices. If you need an overview over all available WebServices just take a look at: http://*your.portal.url*/api/jsonws. Your custom Services created with Liferay's ServiceBuilder will also be listed here.

import com.liferay.portlet.asset.model.AssetEntrySoap;
import com.liferay.portlet.asset.model.AssetVocabularySoap;
import com.liferay.portlet.asset.service.persistence.AssetEntryQuery;
import java.util.List;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import org.json.JSONException;
import org.json.JSONObject;

public class WebServicesClient 
{
    private Client client;
    private WebTarget target;
    
    public WebServicesClient( final String portalUrl, final String username, final String password )
    {
        client = ClientBuilder.newClient();       
        client.register( new Authenticator( username, password ) );  
        client.register( GensonProvider.class );
        target = client.target( portalUrl + "api/jsonws" );        
    }

 public AssetEntrySoap requestAssetEntry( final String entryId ) 
    { 
        Form form = new Form();
        form.param( "entryId", entryId );

        AssetEntrySoap assetEntry = target.path( "/assetentry/get-entry" )
            .request( MediaType.APPLICATION_JSON_TYPE )
            .post( Entity.entity( form, MediaType.APPLICATION_FORM_URLENCODED_TYPE ), AssetEntrySoap.class );

        return assetEntry;
    }
 
    public List getAssetEntries(final String companyId ) 
    { 
        Form form = new Form();
        form.param( "companyId", companyId );
        form.param( "start", "-1" );
        form.param( "end", "-1" );

        List< AssetEntrySoap > assetEntries = target.path( "/assetentry/get-company-entries" )
            .request( MediaType.APPLICATION_JSON_TYPE )
            .post( Entity.entity( form, MediaType.APPLICATION_FORM_URLENCODED_TYPE ), new GenericType< List< AssetEntrySoap > >() { } );
   
        return assetEntries;
    }
}

To perform a valid authentication you can implement an authenticator like this:

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.core.MultivaluedMap;
import javax.xml.bind.DatatypeConverter;

public class Authenticator implements ClientRequestFilter 
{ 
 private final String username;
    private final String password;

    public Authenticator( final String username, final String password ) 
    {
        this.username = username;
        this.password = password;
    }

    public void filter( final ClientRequestContext requestContext ) throws IOException 
    {
        MultivaluedMap headers = requestContext.getHeaders();
        final String basicAuthentication = getBasicAuthentication();
        headers.add( "Authorization", basicAuthentication );
    }

    private String getBasicAuthentication() 
    {
        String token = this.username + ":" + this.password;
        try{
            return "BASIC " + DatatypeConverter.printBase64Binary( token.getBytes( "UTF-8" ) );
        }catch ( UnsupportedEncodingException ex ){
            throw new IllegalStateException( );
        }
    } 
}

If you use Genson for Building your json String, you will have to set useDateAsTimestamp as true in your GensonBuilder, since Liferay uses timestamps as date-fields.

import com.owlike.genson.Genson;
import com.owlike.genson.GensonBuilder;
import javax.ws.rs.ext.ContextResolver;

public class GensonProvider implements ContextResolver< Genson > 
{
    private final Genson genson = new GensonBuilder().useDateAsTimestamp( true ).create();

    @Override
    public Genson getContext( final Class< ? > arg0 ){
        return genson;
    }
}

Testing with JUnit

No Comments »

If you want to write JUnit tests for your application, you can use the following TestRunner which will initialize a liferay context such that you are able to use for example liferay services. However this approach makes it necessary to add portal-impl.jar as a dependency.

public class LiferayJUnitTestRunner
extends BlockJUnit4ClassRunner {

public LiferayIntegrationJUnitTestRunner(Class clazz)
throws InitializationError {

super(clazz);

if (System.getProperty("external-properties") == null) {
System.setProperty("external-properties", "portal-test.properties");
}

InitUtil.initWithSpring();

_testContextHandler = new TestContextHandler(clazz);
}

@Override
protected Statement withAfters(
FrameworkMethod frameworkMethod, Object instance, Statement statement) {

Statement withAftersStatement = super.withAfters(frameworkMethod, instance, statement);

return new RunAfterTestMethodCallback(
instance, frameworkMethod.getMethod(), withAftersStatement,
_testContextHandler);
}

@Override
protected Statement withBefores(
FrameworkMethod frameworkMethod, Object instance, Statement statement) {

Statement withBeforesStatement = super.withBefores(frameworkMethod, instance, statement);

return new RunBeforeTestMethodCallback(
instance, frameworkMethod.getMethod(), withBeforesStatement,
_testContextHandler);
}

public static void run(Class clazz){
Request request=Request.classWithoutSuiteMethod(clazz);
Runner runner=request.getRunner();
RunNotifier notifier=new RunNotifier();
runner.run(notifier);
}

private TestContextHandler _testContextHandler;
}
A sample TestCase looks like that:
@RunWith(LiferayIntegrationJUnitTestRunner.class)
public class SampleTestCase{
@Test
public void testSample() throws Exception {
List users = UserLocalServiceUtil.getUsers(-1, -1);
Assert.assertNotNull(users);
}
}

Creating a service without service-builder

No Comments »

Create your service-project:
1) Create new Liferay-Portlet project
2) clear porlet.xml.

<portlet-app version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xsi:schemalocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">

</portlet-app>

2) create a service.xml file in docroot/WEB-INF



< ?xml version="1.0" encoding="UTF-8"? >
< !DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.2.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_2_0.dtd" >
< service-builder package-path="test" >
 < author >test< /author >
 < namespace >test< /namespace >
 
 < exceptions >

 < /exceptions >
< /service-builder >




3) Right click on service.xml and choose „Liferay - build services“. Service-Builder will create a directory „service“
4)Open project-properties ans choose the „service“-directory as additional source directory
5) All your service-packages and classes should now be created in this directory. choose „Liferay à build services“ or run ant-task „build-service“ and you will get your service-jar in „EB-INF\lib

Deploy your Service:
Choose among three options:
A) Modify your Portlets liferay-plugin-package.properties and declare your service-project as required-deployment-context. When building your service-jar and afterwars building your portel, a copy of service-jar will be copied to your portlets WEB-INF/lib folder. In addition you have to deploy your service  to Liferay.

Advantages:
1.You can modify your service and rebuilt service and portlet without restarting your application server.
Disadvantages:
1. You also have to deploy vour service, otherweise your portlet will not be deployed because of a missing deployment-context
2.Each portlet using your your service will have a seperate service-instance

B) Copy your service.jar to tomcat-x.x.xx\lib\ext

Advantages:
1. All  portlets using your your service will share one service-instance
Disadvantages:
2. When modifying your service you have to copy a new service-jar to your application server and restart it

C) Copy your service.jar to tomcat-x.x.xx\webapps\ROOT\WEB-INF\lib and modify your liferay-plugin-package.properties by adding your service.jar as portal-dependency-jar

Disadvantages:
1.When modifying your service you have to copy a new service-jar to your application server and restart it
2. Each portlet using your your service will have a seperate service-instance

Download sample:
Mirror 0
Mirror 1
Mirror 2

Create Liferay Portlet URLs

No Comments »

You will often have to built a URL leading to a specific portlet without knowing on which page it was placed. In order to find the page (layout) containing your portlet and building a valid LiferayPortletURL you can use the following code:

ThemeDisplay themeDisplay = (ThemeDisplay)liferayPortletRequest.getAttribute(WebKeys.THEME_DISPLAY);
Layout targetLayout = themeDisplay.getLayout(); 
List allLayouts = LayoutLocalServiceUtil.getLayouts(-1, -1);
        
layoutloop:
for(Layout l:allLayouts){
   LayoutTypePortlet layoutTypePortlet = (LayoutTypePortlet)l.getLayoutType();
   List portletIdList = layoutTypePortlet.getPortletIds();
            
   for(String portletId: portletIdList ){
      if(portletId.equalsIgnoreCase(*your portletId*)){
          targetLayout = l;
          break layoutloop;
      }
   }
}
        
LiferayPortletURL targetUrl = 
PortletURLFactoryUtil.create(liferayPortletRequest, *your portletId*, targetLayout .getPlid(), PortletRequest.RENDER_PHASE);

Format file size

No Comments »

Liferay provides

com.liferay.portal.kernel.util.TextFormatter
, which can be used to format the size of a file given in bytes and thus make it human readable. The relevant method is given with two different signatures;
static String  formatStorageSize(double size, Locale locale)
           
static String  formatStorageSize(int size, Locale locale)