Showing posts with label learn and spread. Show all posts
Showing posts with label learn and spread. Show all posts

Saturday, 23 July 2016

How to override liferay class using ext

Ext also known as extension environment in Liferay is used to extend the functionality of Liferay. With the help of liferay extension environment we can modify liferay's core classes. Classes which are available under portal-impl.jar file are liferay's core classes and extending those classes in liferay is possible only with the help of "ext" environment.

There are very few simple steps to write code / extend liferay's core functionality.

Here are the 5 main steps:

1) Create a project in liferay's ext environment
2) Create {CustomName}LocalServiceImpl class extending {Entity}LocalServiceImpl class
3) Register newly created class as a spring bean 
4) Build and deploy
5) Test

Here are the detailed steps:

1) Create a project in liferay's ext environment

Just like any other plug in ext project can be created with "create" command from command prompt. To create a project called "myext" execute below command from "..\liferay-plugins-sdk-{version}\ext" package structure:

F:\..\liferay-plugins-sdk-{version}\ext>create myext "myext"

Once ext project called "myext-ext" is successfuly created you will get to see below message in a command prompt:

BUILD SUCCESSFUL

Total time: 35.173 secs

You can import "myext-ext" project into your eclipse / LR developer studio.

        By default package structure of ext project would look like this:



2) Create {CustomName}LocalServiceImpl class extending {Entity}LocalServiceImpl class

Depending on the requirement we may extend class available in portal-impl.jar file. In our example we will override "UserLocalServiceImpl" class to modify "authenticateByEmailAddress" method.

Lets create a class called "MyUserLocalServiceImpl" extending "UserLocalServiceImpl" class and add it under location "F:\..\liferay-plugins-sdk-{version}\ext\myext-ext\docroot\WEB-INF\ext-impl\src\com\liferay\portal\service\ext\impl".

Here is how "MyUserLocalServiceImpl" class look a like:

public class MyUserLocalServiceImpl extends UserLocalServiceImpl {

public int authenticateByEmailAddress(
long companyId, String emailAddress, String password,
Map<String, String[]> headerMap, Map<String, String[]> parameterMap,
Map<String, Object> resultsMap)
throws PortalException, SystemException {

System.out.println("Inside authenticateByEmailAddress");

return authenticate(
companyId, emailAddress, password, CompanyConstants.AUTH_TYPE_EA,
headerMap, parameterMap, resultsMap);
}

}



Note:
1) Since we need to override "authenticateByEmailAddress" method only hence only that method we will copy and paste into "MyUserLocalServiceImpl" class. Rest all the methods will work/inherit of "UserLocalServiceImpl" class only.


Hence after adding new class our project structure look like this:




3) Register newly created class as a spring bean 

So far we have created a new custom class and overridden a functionality of liferay's default class but liferay will not consider that class until we register MyUserLocalServiceImpl class as a spring bean.

To register newly created class as a spring bean we have to create a file called "ext-spring.xml" under the META-INF folder.

We need to create a "META-INF" folder under the location "F:\..\liferay-plugins-sdk-{version}\ext\myext-ext\docroot\WEB-INF\ext-impl\src" and need to add a file called "ext-spring.xml" inside it.

We need to add below entry inside "ext-spring.xml" file:

<?xml version="1.0"?>

<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-destroy-method="destroy"
default-init-method="afterPropertiesSet"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean
id="com.liferay.portal.service.UserLocalService"
class="com.liferay.portal.service.ext.impl.MyUserLocalServiceImpl" />
</beans>

Above entry specifies the location of the newly created class and registers it as a spring bean.


Note:
1) ext-spring.xml is the default name used by liferay to register new classes as a spring bean. For more details please refer portal.properties -> spring.config property.
2) Default bean entry of the "UserLocalService" class is available under "portal-spring.xml" file. Kindly refer source file for more details/references of other spring beans/classes.

Here is how folder structure look like after adding "ext-spring.xml" file:



4) Build and deploy

Changes related to newly created class is all done now we have to build a war file for ext plugins. Here is the command we need to fire to build a war file of "myext-ext" project.

E:\liferay-plugins-sdk-{version}\ext\myext-ext>ant direct-deploy

Once above command is successfully executed a .war file will be created and placed under "dist" folder. you can copy "myext-ext.war" file and put it in "deploy" folder of liferay bundle.

If your server is already started you may get to see a message that "myext-ext" is successfully deployed you need to restart your server to see the changes of ext environment.

5) Test

After server is restarted just do a login to liferay portal with the help of emailAddress and password and in console you will see a message that "Inside authenticateByEmailAddress" method which is our custom message we placed in authenticateByEmailAddress" method.

We are done!

Cheers!
Henal Saraiya

Friday, 22 July 2016

Use log4j to log content on remote server

Many a times there is a requirement that we need to check the log details of a java program running on a different machines. Most of the time we are dependent on the availability of the machine where java program is running to see and understand actual error (to get local log file, generated on a specific machine). Instead of doing that we can use log4j to capture the live logs generated by java application running on different machines. That way we can independently monitor logs instead of waiting for someone to send us a local log file generated locally.

To achieve remote logging we can make use of "org.apache.log4j.net.SimpleSocketServer" class of log4j.

Here are the steps we need to follow to perform remote logging.

1) Add log4j dependency in pom.xml file
2) Configure log4j-server.properties
3) Start "SimpleSocketServer" to listen remote logging events
4) Configure log4j.properties at client program to specify where log events should be captured
5) Use "org.apache.log4j.Logger" class to add logs
6) Run and verify output

Here are the steps in detail to capture logs on remote server:

1) Add log4j dependency in pom.xml file

In our example we are going to make use of log4j-1.2.17.jar file to start our "SimpleSocketServer" server.

Since our demo application we are going to create in maven we will use below dependency in pom.xml file to automatically download log4j-1.2.17.jar file.

<dependency> 
<groupId>log4j</groupId> 
<artifactId>log4j</artifactId> 
<version>1.2.17</version> 
</dependency>

If you like to use ant to build your project then manually you can download log4j-1.2.17.jar file and add jar file in project's build path.

2) Configure log4j-server.properties

When we start our "SimpleSocketServer" we need to inform to "SimpleSocketServer" that how socket server should store the log events.

In our application log4j-server.properties file looks like this:

#Two arguments we need to specify in below line 1st logger level (DEBUG) in our case, 2nd appender name via which we configure other properties in our case (file)
log4j.rootLogger=DEBUG, file

#Define how the socket server should store the log events
log4j.appender.file=org.apache.log4j.RollingFileAppender

#Here is the name of the file which will capture the log events
log4j.appender.file.File=centralized-error.log

#Below two properties specifies that what should be the maximum size of a log file and up to how many files we need to capture
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=10

#Below properties are used to specify the format of the log events.
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSSS} %p %C %x = %m%n
#log4j.appender.file.layout.ConversionPattern=[%d] [%t] [%m]%n


3) Start "SimpleSocketServer" to listen remote logging events

Now, we can start our "SimpleSocketServer" with few input to it. Below are the inputs we need to provide:

1) Port number : 4713 (in our example)
2) configuration file to "SimpleSocketServer" : log4j-server.properties (in our example)

To start "SimpleSocketServer" we need to put "log4j-1.2.17.jar" and "log4j-server.properties" to a project directory called "C:/remoteloggingexample".

Now we can start our "SimpleSocketServer" as below:

C:/remoteloggingexample>java -classpath log4j-1.2.17.jar org.apache.log4j.net.SimpleSocketServer 4713 log4j-server.properties

4) Configure log4j.properties at client program to specify where log events should be captured

So far we are all set with the server side setup. Now, we need to configure properties at the client side / in our java application.

#Define the log4j configuration for local application
log4j.rootLogger=ALL, server

#We will use socket appender
log4j.appender.server=org.apache.log4j.net.SocketAppender

#Port where socket server will be listening for the log events
log4j.appender.server.Port=4713

#Host name or IP address of socket server
log4j.appender.server.RemoteHost=192.168.10.132


5) Use "org.apache.log4j.Logger" class to add logs

Lets create a dummy program to verify that events are being captured in the log file or not.

import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
import org.apache.log4j.PropertyConfigurator;

public class StudentDemo {

static Logger logger = Logger.getLogger(StudentDemo.class);

static {
PropertyConfigurator.configure("log4j.properties");
}

public static void main(String[] args) {
// These logs will be sent to socket server as configured in log4j.properties
NDC.push("student1 : " + args[0]);
for (int i = 1; i <= 10; i++) {
logger.debug("Student loop started \t" + i);
}
}

}

Note: NDC.push("student1 : " + args[0]); is used to uniquely identify the details of the java application. Since at remote location log file is going to be common across all the places where our java application runs. NDC.push statement helps us to filter the log records.

6) Run and verify output

Once we run the client program we can see that all the logs are being stored on the remote server in our case "192.168.10.132" and a file named "centralized-error.log" will be generated on the remote server which we specified in the "log4j-server.properties" server property file. All the logs which are logged by client program i.e. "StudentDemo" program in our case would be available in "centralized-error.log" file.

We are done!

Cheers!
Henal Saraiya

Sunday, 5 June 2016

How to access/call native (c) file via Java

Many a times its a requirement that from Java we like to access/call a function which is written in a different language other than Java, let's say "C".

Yes, in Java it is possible to invoke native language function.

Here are the steps which needs to be followed to access the a native function.

1) Create a "Student.java" file to call the method "getRank"
2) Compile "Student.java" file to generate the class file
3) Generate a "Student.h" file
4) Create a "StudentResult.c" file to write a method which returns the student result
5) Download "Tiny C" and set class path
6) Compile "C" file created inside step #4
7) Modify "Student.java" program to load generated dll file
8) Run program to see output

We will see an example of retrieving a rank of a student based on the student id. We will pass student id to a function called "getRank". "getRank" function is written inside a "C" language. So in this example not only we are going to access "C" function but we will also see how can we create a native library i.e. ".dll" file.

Here are the steps in detail:

1) Create a "Student.java" file to call the method "getRank"

Here we have created "Student" class which returns the result from the "getRank" method which is written in "C".

/**
Program which calls a native "c" method. It calls the "getRank" method which is written in "C" and returns value of student rank based on the student rollNumber passed via command line argument.
**/

public class Student {

public native int getRank(int rollNumnumber);

public static void main(String[] args) {

Student ja = new Student();
int rank = ja.getRank(Integer.parseInt(args[0]));

System.out.println("Rank of Student Id " + args[0] + " is " + rank);
}
}


2) Compile "Student.java" file to generate the class file

Now, go to the project structure where your java program "Student.java" is available. and fire below command to generate "Student.class" file.
c:/studentrecords>javac Student.java

Once command is successfully executed you should see two files in your project directory (In our case "C:/studentrecords").

Files are:

i)Student.java
ii)Student.class

3) Generate a "Student.h" file

Once "Student.class" is generated next steps is to create a machine generate "Student.h" file.

Fire below command from the project directory to automatically generate "student.h" file.

c:/studentrecords>javah -jni Student

Once command is successfully executed look at the project directory again i.e. "C:/studentrecords".

 Now, you should see below three files:

i) Student.java
ii)Student.class
iii)Student.h (generated in step #3)

FYI, content of the "Student.h" file looks like this

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Student */

#ifndef _Included_Student
#define _Included_Student
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Student
 * Method:    getRank
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_Student_getRank
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif


4) Create a "StudentResult.c" file to write a method which returns the student result

Now, we need to create a "StudentResult.c" file in which "getResult" method resides. A method which we have called from the "Student.java" file.

Here is the sample "StudentResult.c" file.

#include<stdio.h>
#include"jni.h"
#include"Student.h"

JNIEXPORT jint JNICALL Java_Student_getRank (JNIEnv *env, jobject obj, jint rollNumber) {

if(rollNumber == 20) {
return 1;
} else {
return 2;
}
}

In our cases we have used a static logic i.e. if rollNumber which is passed from the java program is 20 then his/her rank is 1 (one) else we will return 2 (two) as a rank for all other rollNumbers.

Note: here method signature we have simply copied from the "Student.h" file. i.e. below line
JNIEXPORT jint JNICALL Java_Student_getRank (JNIEnv *env, jobject obj, jint rollNumber);

We need to save this file in the same project directory. Hence post step #4 we must have below four files in our project directory (C:/studentrecords).

i) Student.java
ii)Student.class
iii)Student.h (generated in step #3)
iv) StudentResult.c (created in step #4)

5) Download "Tiny C" and set class path

We need to compile our "StudentResult.c" file and generate "StudentResult.dll" and "StudentResult.def" file.

To compile "C" file we need a "C" compiler. In our example we will use Tiny C compiler to compile our "Student.c" file.

To download Tiny C, please use link "http://download.savannah.gnu.org/releases/tinycc/".
For our example we have used "tcc-0.9.25-win32-bin.zip" from mentioned link.

Once its downloaded we need to extract the "tcc-0.9.25-win32-bin.zip" to the location "C:/studentrecords/tcc" and set the "C:/studentrecords/tcc" path into the system "path" variable. i.e. path where "tcc.exe" can be found.


6) Compile "C" file created inside step #4

Once "Tiny C" compiler is set to compile our "StudentResult.c" file and path variable is set we need to fire below command.

C:/studentrecords> tcc "StudentResult.c" -I "C:\Program Files (x86)\Java\jdk1.7.0_79\include" -I "C:\Program Files (x86)\Java\jdk1.7.0_79\include\win32" -shared -o StudentResult.dll

Once command is successfully executed it will generate two more files in the location of your project directory (C:/studentrecords).
i.e.
i) StudentResult.def
ii)StudentResult.dll

Hence post step #5 we must have below six files in our project directory (C:/studentrecords).

i) Student.java
ii)Student.class
iii)Student.h (generated in step #3)
iv) StudentResult.c (created in step #4)
v) StudentResult.def (generated in step #6)
vi)StudentResult.dll (generated in step #6)

7) Modify "Student.java" program to load generated dll file

Now, we need to modify the "Student.java" file which we created in step #1 to load newly created "StudentResult.dll" file.

We can use "System.loadLibrary("StudentResult");" to load the library file which we generated in step #6.

For your quick reference this is how our java program looks like after loading "StudentResult" file.

/**
Program which calls a native "c" method. It calls the "getRank" method which is written in "C" and returns value of student rank based on the student rollNumber passed via command line argument.
**/

public class Student {

public native int getRank(int rollNumnumber);

public static void main(String[] args) {

Student ja = new Student();
int rank = ja.getRank(Integer.parseInt(args[0]));

System.out.println("Rank of Student Id " + args[0] + " is " + rank);
}

static {
//Load "StudentResult" library in which "getRank" method is available.
System.loadLibrary("StudentResult");
}
}

FYI, we have loaded "StudentResult file in a static block so that as and when our class is loaded in memory at the same time static block gets executed and StudentResult library is loaded.

8) Run program to see output

We need to compile our "Student.java" program one more time as we modify that file in Step #7.
So we need to fire below command to re-generate Student.class file.

c:/studentrecords>javac Student.java

Now, we have latest "Student.class" file available. To verify output we need to execute "Student" program from command line like this.

1st  run "Student" program with student id "20"

C:/studentrecords> java Student 20
Rank of Student Id 20 is 1

2nd  run "Student" program with student id other than "20" lets say "50"

C:/studentrecords> java Student 50
Rank of Student Id 50 is 2


We are done!

Cheers!
Henal Saraiya

Tuesday, 22 March 2016

How to Create a Liferay Application Startup Event Hook

How to Create a Liferay Application Startup Event Hook

Many a times I have seen that application needs to have a lot of configuration, doing all such configuration manually is time consuming job at the same time its tedious too. Fortunately Liferay provides a way to get configuration done grammatically and get rid of manual configuration. Application Startup Event Hook is useful for writing a configuration logic related to configuration of the system.

Here are the simple steps for creating the Application Startup Event Hook
1    Create a Hook "{startupaction}"
2    Create a custom class / action to be executed for configuration
3    Create a properties file for a Hook
4    Map properties file entry with "liferay-hook.xml"
5    Deploy "{startupaction}" hook
6    Test functionality

Here are the steps in detail
1    Create a Hook "{startupaction}"

    To create a hook from command prompt follow below commands:
    i)    Go to your liferay plugin sdk / hooks
    ii)    Fire a command on command propmpt called e:/lifera.../hook>create startupaction "startupaction"

2    Create a custom class / action to be executed for configuration

    Custom Action class which we create will be executed (run method) at the time of deploying our {startupaction} hook
    Lets say we create a Class/Action called "MyStartUpAction" which is used to create a custom field of an organization called "orgType".
    Here is the sample code for

        package com.startup.action;

        import java.util.List;

        import com.liferay.portal.kernel.events.ActionException;
        import com.liferay.portal.kernel.events.SimpleAction;
        import com.liferay.portal.kernel.exception.PortalException;
        import com.liferay.portal.kernel.exception.SystemException;
        import com.liferay.portal.kernel.util.UnicodeProperties;
        import com.liferay.portal.model.Company;
        import com.liferay.portal.model.Role;
        import com.liferay.portal.model.User;
        import com.liferay.portal.security.auth.PrincipalThreadLocal;
        import com.liferay.portal.security.permission.PermissionChecker;
        import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
        import com.liferay.portal.security.permission.PermissionThreadLocal;
        import com.liferay.portal.service.CompanyLocalServiceUtil;
        import com.liferay.portal.service.RoleLocalServiceUtil;
        import com.liferay.portal.service.UserLocalServiceUtil;
        import com.liferay.portlet.expando.model.ExpandoBridge;
        import com.liferay.portlet.expando.model.ExpandoColumnConstants;
        import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;

        public class MyStartupAction extends SimpleAction {
            /*
             * (non-Java-doc)
             *
             * @see com.liferay.portal.kernel.events.SimpleAction#SimpleAction()
             */
            public MyStartupAction() {
                super();
            }

            /*
             * (non-Java-doc)
             *
             * @see com.liferay.portal.kernel.events.SimpleAction#run(String[] arg0)
             */
            public void run(String[] companyId) throws ActionException {
                // TODO Auto-generated method stub

                System.out.println("Length of arguments " + companyId.length + " value is " + companyId[0]);
                System.out.println("My Startup Action Method has been called..... !!!");
               
                //We like to create a custom field for the resourceType as "organization".
                String modelResource = "com.liferay.portal.model.Organization";
                long resourcePrimKey = 0;
                String name = "orgType";

                ExpandoBridge expandoBridge = ExpandoBridgeFactoryUtil
                        .getExpandoBridge(Long.parseLong(companyId[0]), modelResource,
                                resourcePrimKey);

                UnicodeProperties properties = null;
                try {
                    properties = expandoBridge.getAttributeProperties(name);
                } catch (Exception e) {
                    properties = new UnicodeProperties();
                }

                //Creating a default property for the "orgType" custom field
                int type = ExpandoColumnConstants.STRING;
                properties.setProperty(ExpandoColumnConstants.PROPERTY_HEIGHT, "105");
                properties.setProperty(ExpandoColumnConstants.PROPERTY_WIDTH, "450");

                //This is a mimic to set a custom permission checker. If we dont set this then while adding a new attribute in expando will create a permission checker error. Piece of code from DoAsUserThread class
                setPermissionChecker(companyId);

                try {
                    expandoBridge.addAttribute(name, type);
                } catch (PortalException e) {
                }
                expandoBridge.setAttributeProperties(name, properties);
            }
           
            /*
                Setting up the custom permission checker object
            */
            private void setPermissionChecker(String[] companyId) {
                Company companyqq = null;
                try {
                    companyqq = CompanyLocalServiceUtil.getCompanyById(Long.parseLong(companyId[0]));
                } catch (PortalException | SystemException e1) {
                }
                Role adminRole = null;
                try {
                    adminRole = RoleLocalServiceUtil.getRole(companyqq.getCompanyId(),"Administrator");
                } catch (PortalException | SystemException e1) {
                }
                List<User> adminUsers = null;
                try {
                    adminUsers = UserLocalServiceUtil.getRoleUsers(adminRole.getRoleId());
                } catch (SystemException e1) {
                }

                PrincipalThreadLocal.setName(adminUsers.get(0).getUserId());
                PermissionChecker permissionChecker = null;
                try {
                    permissionChecker = PermissionCheckerFactoryUtil.create(
                            adminUsers.get(0), true);
                } catch (Exception e1) {
                }
                PermissionThreadLocal.setPermissionChecker(permissionChecker);
            }
        }

   
3    Create a properties file for a Hook

    Create a properties file lets say "portal.properties" in our case on the location   
    liferay-plugins-sdk-6.2\hooks\{startupaction}-hook\docroot\WEB-INF\src\portal.properties
   
    Inside the "portal.properties" file add an entry as below of our custom class / action i.e. MyStartupAction in our case
    application.startup.events=com.startup.action.MyStartupAction

   
4    Map properties file entry with "liferay-hook.xml"

    We need to specify the name of the property file inside the "liferay-hook.xml" file. This is the file which Liferay hook will read for all the overridden properties
   
    Here is the sample entry of "liferay-hook.xml"
    <?xml version="1.0"?>
    <!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.2.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_2_0.dtd">

    <hook>
        <portal-properties>portal.properties</portal-properties>
    </hook>

   
5    Deploy "{startupaction}" hook
   
    Alright Then! We are done with our coding / changes for application startup action hook. Just deploy our hook via below command

    i)    Open command Prompt and go to the location of your plugin sdk and hit "ant"
    ii)    e:\...\liferay-plugins-sdk-6.2\hooks\{startupaction}-hook>ant
   
6    Test functionality

Once we deploy our {startupaction} hook in the console we can see below entries which is the proof that our hook is invoked and our custom
field will be created called "orgType" under "organization".







Console Output is:
Length of arguments 1 value is 20155
My Startup Action Method has been called..... !!!


To verify from the Admin console follow below steps

1)    Go to "Admin" -> "Control Panel"
2)    Go to "Configuration" -> "Custom Fields"
3)    Go to "Organization" -> "Edit"
4)    See our newly created custom field called "orgType" is created and available in listing

Great! We are done!

Cheers!
Henal Saraiya

Thursday, 3 December 2015

How to read liferay portlepreferences and read particular key of the preferences

Many a times we like to read the preferences of the portlet which is not of the current portlet scope (Preferences of the other than the current portlet). Liferay provides API called "PortletPreferencesLocalServiceUtil" to get the portletpreferences object / value.

API has methods which returns the one of the two objects :

1) com.liferay.portal.model.PortletPreferences
   This will provide the model object of PortletPreferences. It will not support to directly fetch value of specified key. If we like to get handler to fetch directly value from the key then we need to convert the "com.liferay.portal.model.PortletPreferences" to "javax.portlet.PortletPreferences". Liferay provides the API for this conversion as well:

Here is the quick example:
   //Fetching the list of model object of PortletPreferences

   List<com.liferay.portal.model.PortletPreferences> portletPreferencesObj = PortletPreferencesLocalServiceUtil.getPortletPreferences(themeDisplay.getLayout().getPlid(), portletId);
  
   //Take out the xml / preferences of PortletPreferences Table


   String xmlValue = portletPreferencesObj.get(0).getPreferences();
  
   //Convert the xml into javax.portlet.PortletPreferences i.e. key value pair


   javax.portlet.PortletPreferences portletPreferencesObjWithKeyValue = com.liferay.portlet.PortletPreferencesFactoryUtil.fromDefaultXML(xmlValue);

  
   //Once we have converted portlet preference object we can fetch value of the specified key. "studentId" in our case
                           
   String studentId = portletPreferencesObjWithKeyValue.getValue("studentId",StringPool.BLANK);              


2) javax.portlet.PortletPreferences
    This allows to read the value of the specified key directly:
   
    Here is the quick example:   
    //Returns the "javax.portlet.PortletPreferences" Object

    javax.portlet.PortletPreferences portletPreferencesObj = PortletPreferencesLocalServiceUtil.getPreferences(themeDisplay.getCompanyId()
                            ,PortletKeys.PREFS_OWNER_ID_DEFAULT,PortletKeys.PREFS_OWNER_TYPE_LAYOUT,themeDisplay.getLayout().getPlid(),
                            portletId);
    //Once we have portlet preference object we can fetch value of the specified key. "studentId" in our case 

                          
    String studentId = portletPreferencesObj.getValue("studentId",StringPool.BLANK);   
           

Note: In above API "portletId" is the portletname along with the instance if it is instanceable portlet.                               

We are done!

Cheers!
Henal Saraiya

Saturday, 5 September 2015

How to implement SSL in tomcat

Before we jump into how to implement SSL, lets look at once why SSL is required:

Whenever we want to share any sensitive information from client to server, it is advisable to pass the request in an encrypted mode. SSL help us to pass the details in a secure manner from client to server. A client uses a certificate to authenticate server.

In a market there are few certificate authorities available which validates the server as per the certificate available with the browser / client.

If you want to implement SSL in tomcat its very easy. You just have to follow couple of steps and you will be done with SSL in your application.

Here are four simple steps need to be performed:

1) Generate keystore file
2) Modify server.xml file
3) Restart your server
4) Test

Here are the steps in detailed:

1) Generate keystore file

In java if we want to generate a certificate then we can use the utility called "keytool". Here are the steps one need to follow for creating a certificate:

C:\java\jdk*\bin>keytool -genkey -alias tomcat -keyalg RSA

Enter keystore password:  changeit
What is your first and last name?
  [Unknown]:  hs

Just keep pressing "Return" for all the question which is being asked like 

What is the name of your organizational unit?
What is the name of your organization?
What is the name of your City or Locality?
What is the name of your State or Province?
What is the two-letter country code for this unit?
Is CN=hs, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
  [no]:  yes

Note: default password is "changeit".

After following above steps automatically a file will be generated on the home directory with the name called ".keystore". ex: C:\Users\{UserName}

2) Modify server.xml file

Uncomment the below line inside "\apache-tomcat-*\conf\server.xml" file to support the "https" requests.

<Connector SSLEnabled="true" clientAuth="false" maxThreads="150" port="8443" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS"/>


3) Restart your server

We are almost done with the setup of SSL,  since we have made changes inside "server.xml" file it is mandatory to bounce your server to bring "server.xml" changes.

4) Test

Time to verify whether SSL is really enabled and working or not. To verify hit any of your application's URL with "https". Ex: I have one application available called "student" so to verify default landing page I will hit my URL like this:

https://localhost:8443/student/index.jsp

We are done!

Cheers!
Henal Saraiya

Thursday, 30 July 2015

How to write hibernate application using MySql

This blog will be helpful to create simple java application using hibernate:

To make things very easy we will be taking an example of student. In this example we will be creating a "StudentRecord" table and will insert dummy student data in it.

We will see how "Hibernate" can create a table for us. Hence we don't need to worry about creating a table manually. Our application will take care of not just insertion
of the student record but creating of table as well.

There are few simple steps we need to perform for writing simple hibernate java application.

Here are the main steps:

1. Create Entity Class
2. Create ".hbm" file for the student 
3. Hibernate configuration XML file
4. Create a Dummy Class to test application
5. Run and Verify
6. Trouble Shoot

Let's see the steps in detailed

1. Create Entity Class

This is a POJO class which holds all the properties related to student along with the  setter and getter methods.

Here is the quick code snippet:

package student.persistence;

public class Student {

private int studentId;
private String studentName;
private String email;
private String gender;

public int getStudentId() {
return studentId;
}
public void setStudentId(int studentId) {
this.studentId = studentId;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}

In our case we have used four properties "studentId", "studentName", "email", "gender". Whose value we will be storing inside the table in the proceeding steps:

2. Create ".hbm" file for the student 

For every "POJO" we need to create ".hbm" file. ".hbm" file contains the mapping of "POJO" (Class) with "Relational Table" (StudentRecord) in our case.
At the same time ".hbm" file contains the association between "attributes" of the "POJO" with the "column" of the "Table".
We can also specify the constraint like "primary key" , "composite key" etc in ".hbm" file.

Here is the quick code snippet:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC  
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="student.persistence.Student" table="StudentRecord">
<id name="studentId">
<generator class="assigned"></generator>
</id>
<property name="studentName"></property>
<property name="email"></property>
<property name="gender"></property>
</class>
</hibernate-mapping>

3. Hibernate configuration XML file (.cfg) file

For every application there is one "hibernate.cfg.xml" file. Which is the main mapping file. It contains the details related to database, connection,username,
password,dialect etc. Along with the few hibernate specific properties can also be specified.

Here is the quick reference of "hibernate.cfg.xml" file:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/student</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<mapping resource="student.hbm.xml" />
</session-factory>
</hibernate-configuration>

In our application we have used the "MySQLDialect" which means our application will be creating a table inside "MySql" database.
Property "hibernate.connection.url" contains the details like under which databse/schema our tables should get created. In Url "..../student" we have specified
that means that our table "StudentRecord" will be created under "student" schema.

Property "<mapping resource="student.hbm.xml" />", loads the student.hbm.xml file.
Property "<property name="show_sql">true</property>" will print the all the sql which our application will fire. (Its very helpful for the debugging purpose)


4. Create a Dummy Class to test application

In our java application we will be using "StudentDemo" as an entry point for the application. In our dummy class we will be doing following operations

Load Configuration file ("hibernate.cfg.xml")
Build Session Factory
Open Session
Create, Instantiate, Initialize a student pojo
begin the transaction
save/persist student pojo
commit the transaction
Close Session and Factory respectively.

Here is the code snippet for quick reference:

package student.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import student.persistence.Student;

public class StudentDemo {

    public static void main(String[] args) {

        Configuration cfg = new Configuration();
        cfg.configure("hibernate.cfg.xml");

        SessionFactory factory = cfg.buildSessionFactory();
        Session session = factory.openSession();
        Student student = new Student();
        student.setStudentName("Peter");
        student.setGender("M");
        student.setEmail("peter@test.com");
        
        Transaction tx = session.beginTransaction();
        session.save(student);
        
        System.out.println("Student Record Saved Successfully! ");
        
        tx.commit();
        session.close();
        factory.close();
    }
}


5. Run and Verify

When we run the "StudentDemo" class we can see below console output:

Jul 30, 2015 2:55:35 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.0.0.CR2}
Jul 30, 2015 2:55:35 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Jul 30, 2015 2:55:35 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Jul 30, 2015 2:55:37 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.0.Final}
Jul 30, 2015 2:55:37 PM org.hibernate.boot.jaxb.internal.stax.LocalXmlResourceResolver resolveEntity
WARN: HHH000223: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/hibernate-mapping. Use namespace http://www.hibernate.org/dtd/hibernate-mapping instead. Refer to Hibernate 3.6 Migration Guide!
Jul 30, 2015 2:55:38 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH000402: Using Hibernate built-in connection pool (not for production use!)
Jul 30, 2015 2:55:38 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/student]
Jul 30, 2015 2:55:38 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000046: Connection properties: {user=root, password=****}
Jul 30, 2015 2:55:38 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000006: Autocommit mode: false
Jul 30, 2015 2:55:38 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Jul 30, 2015 2:55:40 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
Jul 30, 2015 2:55:42 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000227: Running hbm2ddl schema export
Hibernate: 
    drop table if exists StudentRecord
Hibernate: 
    create table StudentRecord (
        studentId integer not null,
        studentName varchar(255),
        email varchar(255),
        gender varchar(255),
        primary key (studentId)
    )
Jul 30, 2015 2:55:43 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Student Record Saved Successfully! 
Hibernate: 
    insert 
    into
        StudentRecord
        (studentName, email, gender, studentId) 
    values
        (?, ?, ?, ?)
Jul 30, 2015 2:55:43 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH000030: Cleaning up connection pool [jdbc:mysql://localhost:3306/student]


We can see that first of all hibernate goes to drop the table if the table already exist. Then it creates the table using auto generated "Create" script.
and then it insert the record into the "StudentRecord" table.

Here is the snippet we can see in the database:




6. Trouble Shoot

Overall our application package structure should look like this:



For more trouble shoot please refere "http://technoknowledgespread.blogspot.in/2015/07/common-errors-while-configuring.html"

Cheers!
Henal Saraiya
(Lead Consultant)
CIGNEX Datamatics

Common errors while configuring a hibernate application

I have seen that people struggle a lot while setting up the hibernate application.

Here is a blog which will help the user for the common errors and its resolution.

1) NoClassDefFoundError : org/apache/commons/logging/LogFactory

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.hibernate.cfg.Configuration.<clinit>(Configuration.java:110)
at student.test.StudentDemo.main(StudentDemo.java:14)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 2 more

Resolution : Need to include jar file "commons-logging-1.2.jar"



2) NoClassDefFoundError : org/dom4j/io/SAXReader

Exception in thread "main" java.lang.NoClassDefFoundError: org/dom4j/io/SAXReader
at org.hibernate.util.XMLHelper.createSAXReader(XMLHelper.java:35)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1168)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1112)
at student.test.StudentDemo.main(StudentDemo.java:15)
Caused by: java.lang.ClassNotFoundException: org.dom4j.io.SAXReader
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 4 more

Resolution : Need to include jar file "dom4j-1.6.1.jar"



3) NoClassDefFoundError: org/apache/commons/collections/SequencedHashMap

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/collections/SequencedHashMap
at org.hibernate.mapping.Table.<init>(Table.java:32)
at org.hibernate.cfg.Mappings.addTable(Mappings.java:120)
at org.hibernate.cfg.HbmBinder.bindRootPersistentClassCommonValues(HbmBinder.java:251)
at org.hibernate.cfg.HbmBinder.bindRootClass(HbmBinder.java:236)
at org.hibernate.cfg.HbmBinder.bindRoot(HbmBinder.java:152)
at org.hibernate.cfg.Configuration.add(Configuration.java:362)
at org.hibernate.cfg.Configuration.addInputStream(Configuration.java:400)
at org.hibernate.cfg.Configuration.addResource(Configuration.java:449)
at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:1263)
at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:1235)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1217)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1184)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1112)
at student.test.StudentDemo.main(StudentDemo.java:15)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.collections.SequencedHashMap
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 14 more

Resolution : Need to include jar file "commons.collections-3.2.1"



4) NoClassDefFoundError: net/sf/ehcache/CacheException

Exception in thread "main" java.lang.NoClassDefFoundError: net/sf/ehcache/CacheException
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at org.hibernate.cfg.SettingsFactory.createCacheProvider(SettingsFactory.java:323)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:219)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:1463)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1004)
at student.test.StudentDemo.main(StudentDemo.java:17)
Caused by: java.lang.ClassNotFoundException: net.sf.ehcache.CacheException
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 10 more


Resolution : Need to include jar file "ehcache-core-2.4.3"



5) NoClassDefFoundError: javax/transaction/Synchronization

INFO: Default entity-mode: pojo
Exception in thread "main" java.lang.NoClassDefFoundError: javax/transaction/Synchronization
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1005)
at student.test.StudentDemo.main(StudentDemo.java:17)
Caused by: java.lang.ClassNotFoundException: javax.transaction.Synchronization
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 2 more


Resolution : Need to include jar file "jta.jar"



6) NoClassDefFoundError: net/sf/cglib/core/KeyFactory

INFO: Default entity-mode: pojo
Exception in thread "main" java.lang.NoClassDefFoundError: net/sf/cglib/core/KeyFactory
at org.hibernate.impl.SessionFactoryImpl.<clinit>(SessionFactoryImpl.java:321)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1005)
at student.test.StudentDemo.main(StudentDemo.java:17)
Caused by: java.lang.ClassNotFoundException: net.sf.cglib.core.KeyFactory
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 3 more


Resolution : Need to include jar file "cglib-2.1_3"



7) NoClassDefFoundError: org/objectweb/asm/Type

INFO: Default entity-mode: pojo
Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type
at net.sf.cglib.core.TypeUtils.parseType(TypeUtils.java:180)
at net.sf.cglib.core.KeyFactory.<clinit>(KeyFactory.java:66)
at org.hibernate.impl.SessionFactoryImpl.<clinit>(SessionFactoryImpl.java:321)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1005)
at student.test.StudentDemo.main(StudentDemo.java:17)
Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.Type
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 5 more


Resolution : Need to include jar file "asm-1.3.3"

Cheers!
Henal Saraiya
(Lead Consultant)
CIGNEX Datamatics

Monday, 20 July 2015

How to use Error Handlers in Java EE

Client sends a request to the Server for a specific resource. Sometimes it is possible that due to one or another reason server sends an Http status code (related to error) to the client, instead of actual response to the client.

In Java EE it is possible to redirect or show a specific error page as and when any particular error message comes up.

There are two simple steps to be performed for "Error Handlers"

1) Modify web.xml (deployment descriptor) file to add "Error Handlers"
2) Add a JSP to be shown when an error occurs
3) Run and Verify

Here are the detailed steps:

1) Modify web.xml (deployment descriptor) file to add "Error Handlers"

<error-page>
        <error-code>404</error-code>
        <location>/login/errors/pagenotfound.jsp</location>
</error-page>

Here, we have configured "Error Handler" for the Http status code "404". It is the code for the resource not found. As and when we hit the URL or request for the
resource which server can not find at that time server will return Http status code "404".

2) Add a JSP to be shown when an error occurs

Whenever server sends 404 error code at that time JSP available inside folder "WebContent/login/errors/pagenotfound.jsp" will be shown to the user instead of technical message
which layman user can not understand.

In our case we have written a message "Hey requested resource not found"

3) Run and Verify

Once above steps are done just Build and deploy your application on the server. To understand the difference quickly lets look at the two snaps when we hit
URL "http://localhost:8080/student/MyLogin"

Before "Error Handlers"



After "Error Handlers"




Cheers!
Henal Saraiya
(Lead Consultant)
CIGNEX Datamatics

How to use HttpSessionBindingListener in Java EE

In dynamic web application user may like to track as and when object gets "bound" and "unbound" from the session object. In Java EE it is possible to achieve through "Listeners".

HttpSessionBindingListener has below two methods:

1) public void valueUnbound(HttpSessionBindingEvent arg0)
2) public void valueBound(HttpSessionBindingEvent arg0)

If we want to perform any action while object is associated or removed from the "HttpSession" then below three steps needs to be performed:

1) Modify web.xml (deployment descriptor) file to add listener
2) Add a class which implements "HttpSessionBindingListener"
3) Run and Verify

Lets see the steps in detailed:

1) Modify web.xml (deployment descriptor) file to add listener

web.xml file will be read / looked upon by the container while loading any of the project. To inform container about "HttpSessionBindingListener" we need to add below
lines in it:

<listener>
<listener-class>com.listener.Student</listener-class>
</listener>

2) Add a class which implements "HttpSessionBindingListener"

Here is the code snippet for the  quick reference:

public class Student implements HttpSessionBindingListener {

    public Student() {
    }

    public void valueUnbound(HttpSessionBindingEvent arg0) {
    System.out.println("Student Object is Unbound");
    }

    public void valueBound(HttpSessionBindingEvent arg0) {
        System.out.println("Student Object is Bound");
    }
}


As we can see there are two methods "valueUnbound" and "valueBound" which will be called at the time of "Student" object gets added or removed to and from the HttpSession object respectively.

3) Run and Verify

Lets create a dummy servlet called "HttpSessionBindEventTest" which has below "doGet" method which adds and removes the "Student" object in HttpSession.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Student student = new Student();
request.getSession().setAttribute("student", student); //Line #1
request.getSession().removeAttribute("student"); //Line #2
}

when we run the Url : "http://localhost:8080/student/HttpSessionBindEventTest" and hit enter below lines we can see inside logs:

INFO: Server startup in 578 ms
Student Object is Bound //Line #1
Student Object is Unbound //Line #2

Line #1 is the result of 1st line of the "doGet" method (HttpSessionBindEventTest)
Line #2 is the result of the 2nd line of the "doGet" method (HttpSessionBindEventTest)

Cheers!
Henal Saraiya
(Lead Consultant)
CIGNEX Datamatics