Sparkles

that were shone when I got tempered!

Archive for the ‘Java’ Category

Java 8 – Method References

leave a comment »

Method references can be used with the Lambda Expressions. They can be used to refer method of functional interface. It allows to reuse the method implementation among Lambda expressions.

Simple example with zero parameter

@FunctionalInterface 
interface MyInterface{  
    void display();  
}  
public class Example {

    public void myMethod(){  
		System.out.println("Instance Method");  
    }  

    public static void main(String[] args) {  
		Example obj = new Example();   
		MyInterface ref = obj::myMethod;  
		ref.display();  
    }  

}

Simple example with two parameters and for static method.

@FunctionalInterface 
interface MyInterface{  
	void display(String one, String two);  
}  
public class Example {

	public static void myMethod(String one, String two){  
		System.out.println("Instance Method for "+one+" and " + two);  
	}  

	public static void main(String[] args) {  
		MyInterface ref = Example::myMethod;  
		ref.display("ONE", "TWO");  
	}  

}

Simple example with one parameter and using constructor.

@FunctionalInterface 
interface MyInterface{  
    Hello display(String say);  
}  

class Hello{  
    public Hello(String say){  
        System.out.print(say);  
    }  
}

public class Example {  
    public static void main(String[] args) {
        MyInterface ref = Hello::new;  
        ref.display("Hello World!");  
    }  
}

References :.

Advertisements

Written by Namal Fernando

April 16, 2018 at 9:31 pm

Posted in Java

Tagged with

Java 8 – Lambda Expressions

leave a comment »

This is available since Java 8.
This is very usefull in java Collection Framework.

Lambda expressions can be only used with the functional interfaces. (An interface which has only one abstract method). Functional Interfaces can be annotated with @FunctionalInterface.
Here, because of Lambda expressions, we don’t need to define the method again to provide the implementation for abstract method of the Functional Interface.

Java Lambda expressions are treated as functions. So, no .class file will be created.

 

Java Lambda Expression syntax :

(argument-list) -> {body}

  • argument-list : empty / single or multiple
  • body : expressions and statements for the Lambda expressions.

 

Basic Exaple


@FunctionalInterface
interface Drawable{
public void draw();
}

int width=10;

// without Lambda
Drawable d = new Drawable(){
public void draw(){
System.out.println("Drawing "+width);
}
};

// with Lambda
Drawable d2 = () -> {
System.out.println("Drawing "+width);
};

d2.draw();

 

No Parameter Example


interface Sayable{
public String say();
}

Sayable s = ()-> {
return "I have nothing to say.";
};

System.out.println(s.say());

 

Multiple Parameters


interface Addable{
int add(int a,int b);
}

// Multiple parameters in lambda expression
Addable ad1 = (a,b)->(a+b);
System.out.println(ad1.add(10,20));

// Multiple parameters with data type in lambda expression
Addable ad2 = (int a,int b) -> (a+b);
System.out.println(ad2.add(100,200));

 

forEach loop


List list=new ArrayList();
list.add("ankit");
list.add("mayank");
list.add("irfan");
list.add("jai");

list.forEach(
(n)->System.out.println(n)
);

 

References :

Written by Namal Fernando

April 15, 2018 at 7:50 pm

Posted in Java

Tagged with ,

Install java 8, changing the versions and set up eclipse

leave a comment »

1. Install java 8

	$ sudo add-apt-repository ppa:webupd8team/java
	$ sudo apt-get update
	$ sudo apt-get install oracle-java8-installer
	

2. Verify the java version by using the following command

	$ java -version
	

3. You can set the default version by using the below command

	sudo apt-get install oracle-java8-set-default
	

4. Changing the java version when there are multiple versions.
4.1 Check the avilable java versions

	$ sudo update-alternatives --display java

	namal@namal:~$ sudo update-alternatives --display java
	[sudo] password for namal: 
	java - auto mode
	  link currently points to /usr/lib/jvm/java-8-oracle/jre/bin/java
	/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java - priority 1071
	  slave java.1.gz: /usr/lib/jvm/java-7-openjdk-amd64/jre/man/man1/java.1.gz
	/usr/lib/jvm/java-8-oracle/jre/bin/java - priority 1072
	  slave java.1.gz: /usr/lib/jvm/java-8-oracle/man/man1/java.1.gz
	Current 'best' version is '/usr/lib/jvm/java-8-oracle/jre/bin/java'.
	

4.2 Config to use another java version

	$ sudo update-alternatives --config java

	namal@namal:~$ sudo update-alternatives --config java
	There are 2 choices for the alternative java (providing /usr/bin/java).

	  Selection    Path                                            Priority   Status
	------------------------------------------------------------
	* 0            /usr/lib/jvm/java-8-oracle/jre/bin/java          1072      auto mode
	  1            /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java   1071      manual mode
	  2            /usr/lib/jvm/java-8-oracle/jre/bin/java          1072      manual mode

	Press enter to keep the current choice[*], or type selection number: 
	

4.3 Double check the java version

	$ java -version

	namal@namal:~$ java -version
	java version "1.8.0_91"
	Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
	Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
	

5. Change the java version using by the IDE ( eg: eclipse)
-vm
/usr/lib/jvm/java-8-oracle/jre/bin
-vmargs
-Dosgi.requiredJavaVersion=1.8

 

References 

 

Written by Namal Fernando

June 16, 2016 at 6:59 am

Posted in Eclipse, Java, Linux, TroubleShooting

Tagged with , ,

Implement RollingPerInvoke Appender using org.apache.log4j.Logger

leave a comment »

Requirement :

  1. Log data using org.apache.log4j.Logger.
  2. Log data with a unique trace id in log4j pattern.
  3. Log data in seperate files per each invoke.
  4. Log data seperate folders per each supplier threads (eg : DerbySoftImpl, HBSIImpl, HotelbedsImpl, SynxisImpl) and levels (eg : Availabiity, Reservation, Cancellation) at run time.

Approach :

  1. Log data using org.apache.log4j.Logger. :
    We use org.apache.log4j.Logger to log data (eg : logger.info(data))
  2. Log data with a unique trace id in log4j pattern.
    We do this through the org.apache.log4j.MDC
  3. Log data in seperate files per each invoke.
    We create a custome Appender extending org.apache.log4j.FileAppender and override the file name with MDC String and System milliseconds
  4. Log data seperate folders per each supplier threads (eg : DerbySoftImpl, HBSIImpl, HotelbedsImpl, SynxisImpl) and levels (eg : Availabiity, Reservation, Cancellation) at run time.
    In the created custome Appender, we create the new folder structure using the extracted values from mDCStr and override the FileAppender’s folder path using created one.

LogDataClient.java
This is the demo class for the RollingPerInvokeImplemnetation.
In this case, there are two set of threads. Air threads and hotel threads. Actually air threads are kind of control threads here. It logs data to one seperate file (daily) by appending to it. And hotel threads will do logging data to seperate files in each invoke. All these happens in multithreaded environment. So, LogDataClient initializes the hotel and air supplier threads.

Hotel Supplier Threads. (eg : DerbySoftImpl, HBSIImpl, HotelbedsImpl, SynxisImpl)
In each invoke, it calls logData method passing data to be logged and the unique ID (traceid). We have done this in multiple times to create a realtime traffic in there. So, when there are 10 supplier threads per each supplier and they invoked logdata method 10 times by each supplier thread, that means there are 10 calls per supplier thread.
eg :

Log4jFileLogger.logData("<RESPONSE><DERBY_RS><RESPONSE>","derbysoft|Availabiity|Response|"+UUID.randomUUID());

Log4jFileLogger
This is the class that declare and initializes org.apache.log4j.Logger instance and invoke it with data passed by the suppier thread. unique id will be passed to the logger via MDC.
In this case we have make the logData method as synchronized one to avoid being conflict with the FileAppender (to be discussed little bit later here).


 public static synchronized void logData(String data, String mDCStr) {

 MDC.put("ridelogid", mDCStr);

 DOMConfigurator.configure("log4j.xml");
 logger.info(data);

 MDC.remove("ridelogid");
 }

In this case, for hotel supplier threads we invoke the log4j.hotel.Log4jFileLogger and for air supplier threads we invoke log4j.air.Log4jFileLogger. We locate these Log4jFileLoggers to seperate packages. So, when the logger is invoked (eg : logger.info()), it looks at the relevant <logger> tag the log4j.xml.
eg :

<logger name="log4j.hotel">
<appender-ref ref="HOTEL_AVAILABIITY" />
</logger>

<logger name="log4j.air">
<appender-ref ref="loggers initialized through the classes in log4j.hotel will use the appernder named HOTEL_AVAILABIITY" />
</logger>

So, in this case, loggers initialized through the classes in log4j.hotel (Logger logger = Logger.getLogger(log4j.hotel.Log4jFileLogger.class);) will use the appernder named HOTEL_AVAILABIITY and loggers initialized through the classes in log4j.hotel will use the appernder named loggers initialized through the classes in log4j.air will use the appernder named AIR_AVAILABIITY.

<appender name="HOTEL_AVAILABIITY" class="log4j.RollingPerInvokeFileAppender">
<param name="append" value="false" />
<param name="File" value="/var/log/rezg/app/bonologs/fileNamex" />
<param name="Threshold" value="INFO" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%X{ridelogid}] %m%n" />
</layout>
</appender>

<appender name="AIR_AVAILABIITY" class="org.apache.log4j.DailyRollingFileAppender">
<param name="append" value="true" />
<param name="File" value="/var/log/rezg/app/bono-airlogs/airlogs.log" />
<param name="Threshold" value="INFO" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] %m%n" />
</layout>
</appender>

Then in those apenders, HOTEL_AVAILABIITY uses a custome fileAppender log4j.RollingPerInvokeFileAppender we implemented. And AIR_AVAILABIITY uses inbuilt org.apache.log4j.DailyRollingFileAppender to log Data passed through the logger invocation in relevant Log4jFileLogger (eg : logger.info(data)) .
In this case unique trace Id put to the MDC (eg : MDC.put(“ridelogid”, mDCStr);) in log4j.hotel.Log4jFileLogger, will be passed to relevant appender via log4j ConversionPattern (eg : <param name=”ConversionPattern” value=”%d [%X{ridelogid}] %m%n” />) to be logged with the log data.
As mentioned earlier, the real implementation will be in HOTEL_AVAILABIITY appender. So, moving forward we will discuss about the HOTEL_AVAILABIITY. In AIR_AVAILABIITY appender it will just append the data to a daily rolling log file in old school style :).

So, when the MDC string is put and logger.info(data) method is invoked, log4j.RollingPerInvokeFileAppender will be invoked passing the MDC string to it via the ConversionPattern.

log4j.RollingPerInvokeFileAppender
RollingPerInvokeFileAppender is a org.apache.log4j.FileAppender. (RollingPerInvokeFileAppender extends FileAppender). So, the core implementation happens in the org.apache.log4j.FileAppender. And we have override some methods (eg : append(LoggingEvent event)) suit for our requirement mentioned at the top.
So, here, basically, what we are doing is taking the MDC string set in the invoke, create the new file name with relavant folder structure using the parameters passed in MDC string for each millisecond.

append method :

 @Override
 public void append(LoggingEvent event) {

 String mDCString = (String) event.getMDC("ridelogid");

 modifyLogFileName(mDCString);

 super.append(event);

 }

As mentioned, this is an overriden method from org.apache.log4j.FileAppender.
In this case, first we get the mDCString via event.getMDC(“ridelogid”) and pass the modifyLogFileName method to modify and set the relavant file name with relevant folder structure. Then it calls org.apache.log4j.FileAppender’s append method to do the rest (eg : super.append(event)).

modifyLogFileName method :

Here first we create a file instance with the default file name mentioned in the appender (eg : <param name=”File” value=”/var/log/rezg/app/bonologs/fileNamex” />).
We will use this to get the root folder (eg : /var/log/rezg/app/bonologs/).

 final File logFile = new File(fileName);
 String rootFolder = logFile.getParent();

Then we identify the required parameters from the MDC string (eg : derbysoft|Availabiity|Response|5395de83-f507-436b-8b4d-25e3ff86ce33) and create the new folder path.

 String[] fileProps = mDCString.split("\\|");

 String vendorId = null;
 String traceId = null;
 String flow = null;
 String type = null;

 try { vendorId = fileProps[0];} catch (Exception e) {}
 try { flow = fileProps[1];} catch (Exception e) {}
 try { type = fileProps[2];} catch (Exception e) {}
 try { traceId = fileProps[3];} catch (Exception e) {}

 String newfolderPath = rootFolder + File.separator + vendorId + File.separator + flow;

Then we create the new Folder structure (for the first time only) (requirement 4)

 File file = new File(newfolderPath); 
 if(! file.isDirectory()) file.mkdirs(); 

Then we create the new file name with the System millisecond along with the mDCString. This will create unique file per each invoke (requirement 3).


String newfileName = newfolderPath + File.separator + mDCString.replaceAll("\\|", "-") + "_" + System.currentTimeMillis() + ".log";

Then we set the created newfileName to the org.apache.log4j.FileAppender’s setFile() method.

setFile(newfileName, fileAppend, bufferedIO, bufferSize);

After this, modifyLogFileName method is comlpleted and it will log the data through log4j (requirement 1) with MDC string (requirement 2) as default org.apache.log4j.FileAppender behaviour.

Note : we must synchronized the logData method in Log4jFileLogger to avoid conflicts with creating the newfolderPath for each mDCString (ridelogid).

You can find the comlplet source code at https://github.com/namalfernandolk/log4j-rolling-per-invoke.git

Written by Namal Fernando

January 20, 2016 at 5:51 am

Posted in Java, log4j

Tagged with , ,

Measuring Memory of JAVA objects

leave a comment »

Build the JAMM Master Project.

This project includes all the implemnetation to measure the memoory of the Java Objects. We are going to build it and package it to a jar file so that we can use in our client to do memory measurements.

1. Get the jeblis-jamm client project from here.

2. Build it and package it to a jar file.

3. Specify the org.github.jamm.MemoryMeter class as the Premain-Class in jar file’s MANIFEST.MF.

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: namal
Build-Jdk: 1.7.0_03
Premain-Class: org.github.jamm.MemoryMeter

Now your jar is ready to use (jamm-0.3.2-SNAPSHOT.jar).

I have added my project also built using above steps in here.

Build the JAMM Client Project.

1. Create a new JAVA project and add the JAMM-Master jar file built in above step.

TestMemory.java


public class TestMemory {

public static void main(String[] args) {

String str = &amp;quot;Namal Fernando&amp;quot;;

ArrayList&amp;lt;String&amp;gt; strList = new ArrayList&amp;lt;String&amp;gt;();
strList.add(str);
strList.add(str+&amp;quot;1&amp;quot;);
strList.add(str+&amp;quot;2&amp;quot;);
strList.add(str+&amp;quot;3&amp;quot;);
strList.add(str+&amp;quot;4&amp;quot;);

MemoryMeter memoryMeter = new MemoryMeter().enableDebug();
System.out.println(&amp;quot;main().General Measure : &amp;quot; + memoryMeter.measure(strList));
System.out.println(&amp;quot;main().Deep Measure : &amp;quot; + memoryMeter.measureDeep(strList));
System.out.println(&amp;quot;main().Count Child : &amp;quot; + memoryMeter.countChildren(strList));

}

}

2. Run the TestMemory class giving the below VM Arguments to point the JAMM-Master jar file (jamm-0.3.2-SNAPSHOT.jar) built in above step as javaagent for memory measurement.

-javaagent:/rezsystem/workspace/jamm-client/lib/jamm-0.3.2-SNAPSHOT.jar

Output will be looked like this.

main().General Measure : 24

root [java.util.ArrayList] 432 bytes (24 bytes)
|
+–elementData [java.lang.Object[]] 408 bytes (56 bytes)
|
+–0 [java.lang.String] 64 bytes (24 bytes)
| |
| +–value [char[]] 40 bytes (40 bytes)
|
+–1 [java.lang.String] 72 bytes (24 bytes)
| |
| +–value [char[]] 48 bytes (48 bytes)
|
+–2 [java.lang.String] 72 bytes (24 bytes)
| |
| +–value [char[]] 48 bytes (48 bytes)
|
+–3 [java.lang.String] 72 bytes (24 bytes)
| |
| +–value [char[]] 48 bytes (48 bytes)
|
+–4 [java.lang.String] 72 bytes (24 bytes)
|
+–value [char[]] 48 bytes (48 bytes)

main().Deep Measure : 432

root [java.util.ArrayList]
|
+–elementData [java.lang.Object[]]
|
+–0 [java.lang.String]
| |
| +–value [char[]]
|
+–1 [java.lang.String]
| |
| +–value [char[]]
|
+–2 [java.lang.String]
| |
| +–value [char[]]
|
+–3 [java.lang.String]
| |
| +–value [char[]]
|
+–4 [java.lang.String]
|
+–value [char[]]

main().Count Child : 12

This JAMM Client Project is available in here.

Written by Namal Fernando

December 23, 2015 at 8:56 am

Posted in Java, Performance

Tagged with , , ,

Write XMPP client using Smack API

leave a comment »

Smack is written in Java. So, it is cross platform. Current version can be downloaded from here.

To start with this, create a Java Project (eg : XMPPProject) and, copy the “smack.jar” and “smackx.jar” files into your classpath.

These are two main classes for this application.

XmppManager.java


package com.javacodegeeks.xmpp;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;

public class XmppManager {

private static final int packetReplyTimeout = 500; // millis

private String server;
private int port;

private ConnectionConfiguration config;
private XMPPConnection connection;

private ChatManager chatManager;
private MessageListener messageListener;

public XmppManager(String server, int port) {
this.server = server;
this.port = port;
}

public void init() throws XMPPException {

System.out.println(String.format("Initializing connection to server %1$s port %2$d", server, port));

SmackConfiguration.setPacketReplyTimeout(packetReplyTimeout);

config = new ConnectionConfiguration(server, port);
config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(SecurityMode.disabled);

connection = new XMPPConnection(config);
connection.connect();

System.out.println("Connected: " + connection.isConnected());

chatManager = connection.getChatManager();
messageListener = new MyMessageListener();

}

public void performLogin(String username, String password) throws XMPPException {
if (connection!=null &amp;&amp; connection.isConnected()) {
connection.login(username, password);
}
}

public void setStatus(boolean available, String status) {

Presence.Type type = available? Type.available: Type.unavailable;
Presence presence = new Presence(type);

presence.setStatus(status);
connection.sendPacket(presence);

}

public void destroy() {
if (connection!=null &amp;&amp; connection.isConnected()) {
connection.disconnect();
}
}

public void sendMessage(String message, String buddyJID) throws XMPPException {
System.out.println(String.format("Sending mesage '%1$s' to user %2$s", message, buddyJID));
Chat chat = chatManager.createChat(buddyJID, messageListener);
chat.sendMessage(message);
}

public void createEntry(String user, String name) throws Exception {
System.out.println(String.format("Creating entry for buddy '%1$s' with name %2$s", user, name));
Roster roster = connection.getRoster();
roster.createEntry(user, name, null);
}

class MyMessageListener implements MessageListener {

@Override
public void processMessage(Chat chat, Message message) {
String from = message.getFrom();
String body = message.getBody();
System.out.println(String.format("Received message '%1$s' from %2$s", body, from));
}

}

}

XmppTest.java


package com.javacodegeeks.xmpp;

public class XmppTest {

public static void main(String[] args) throws Exception {

String username = "testuser1";
String password = "testuser1pass";

XmppManager xmppManager = new XmppManager("myserver", 5222);

xmppManager.init();
xmppManager.performLogin(username, password);
xmppManager.setStatus(true, "Hello everyone");

String buddyJID = "testuser2";
String buddyName = "testuser2";
xmppManager.createEntry(buddyJID, buddyName);

xmppManager.sendMessage("Hello mate", "testuser2@myserver");

boolean isRunning = true;

while (isRunning) {
Thread.sleep(50);
}

xmppManager.destroy();

}

}

 

Description :
XMPPConnection – to Connect

This is basically to connect to the remote server. Connecting and performing the Login can be done as follows :

// Create a connection to the igniterealtime.org XMPP server.
XMPPConnection connection = new XMPPConnection("myxmppserver.com");
// Connect to the server
connection.connect();
// Most servers require you to login before performing other tasks.
connection.login("myuser", "mypass");

 

ConnectionConfiguration – to configure sohisticated conection attributes

This can be used to achieve more sophisticated connection attributes. In this case, various parameters can be configured (server host, port and securrity -encrypt- issues). You can use SmackConfiguration class to configure an internal Smack stack.


ConnectionConfiguration config = new ConnectionConfiguration(serverHost, serverPort);
XMPPConnection connection = new XMPPConnection(config);
connection.connect();
connection.login("myuser", "mypass");

 

ChatManager – to manages chats
From a valid XMPPConnection, you can recive a ChatManager object. This keeps a referenc to all current chats and it allows you to create chat instances (series of messages sent between two users). Chat objects can send messages to the other participants. These messages can be a plain String or construted XMPP messages represented by the Message class.

 

Message class – messages
Message class provides the direct access to all message attributes (eg : message types).

 

MessageListener – to listen
To process incoming messages, you must implement the MessageListener and attach it to the chat.


ChatManager chatManager = connection.getChatManager();
Chat chat = chatManager.createChat("mybuddy", new MyMessageListener());
chat.sendMessage(message);

 

Presence – to setup the status
You can set your online status using the Presence class.


Presence presence = new Presence(Presence.Type.available);
presence.setStatus("What's up everyone?");
connection.sendPacket(presence);

 

Roster – allocate user(s)
A new buddy can be allowcated to your list by using the Roasterr class. A user’s Roaster is a collection of users a persion recieves presence updates for. A user can be associaated with a group too.


Roster roster = connection.getRoster();
roster.createEntry(user, name, null);

 

Note :
In this example no security authentication is done (it is disabled). So, there’s no any protection on the credentials and the messages and the messages that has been exchanged.
Here, an infinite loop has been created (via isRunning boolean) to send the message from the other client and see the response from the console. In real time situaations, this must be set as false if the program exit. And the thread must be slept for some time otherwise machine’s CPU will be much higher.

You can find the project in here.

Related Articles :

Written by Namal Fernando

December 18, 2015 at 6:44 am

Posted in Smack API

Tagged with , , ,

Manage Google Calendars in Java

leave a comment »

Do Step 1 as mentioned in [developers.google.com]

Step 1: Turn on the Google Calendar API

  1. Use this wizard to create or select a project in the Google Developers Console and automatically turn on the API.
  2. Click Continue, then Go to credentials.
  3. At the top of the page, select the OAuth consent screen tab. Select an Email address, enter a Product name if not already set, and click the Save button. (These are the options you will display to the user when you asking for the permission for the app via consent screen).
  4. Select the Credentials tab, click the Add credentials button and select OAuth 2.0 client ID.
  5. Select the application type Other, enter the name of the app “eg : Google Calendar API Quickstart”, and click the Create button.
  6. Click OK to dismiss the resulting dialog.
  7. Click the (Download JSON) button to the right of the client ID.
  8. Move this file to your working directory and rename it client_secret.json. This is the one that you will use to communicate with the Google app via Java program.

 

This is the Java class that you can use to manage the Calenders.

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.client.util.DateTime;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.calendar.model.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

public class CalendarQuickstart {

private static final String APPLICATION_NAME = "Google Calendar API Java Quickstart";

private static final java.io.File DATA_STORE_DIR = new java.io.File(
System.getProperty("user.home"), ".credentials/calendar-java-quickstart-1.0.0");

private static FileDataStoreFactory DATA_STORE_FACTORY;
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

private static HttpTransport HTTP_TRANSPORT;

private static final List&lt;String&gt; SCOPES = Arrays.asList(CalendarScopes.CALENDAR);

static {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
} catch (Throwable t) {
t.printStackTrace();
System.exit(1);
}
}

/**
* Creates an authorized Credential object.
* @return an authorized Credential object.
* @throws IOException
*/
public static Credential authorize() throws IOException {

InputStream in = CalendarQuickstart.class.getResourceAsStream("/client_secret_1.0.0.json");
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline")
.build();

Credential credential = null;
try { credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("namal");} catch (Exception e) {}

System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());

return credential;
}

/**
* Build and return an authorized Calendar client service.
* @return an authorized Calendar client service
* @throws IOException
*/
public static com.google.api.services.calendar.Calendar getCalendarService() throws IOException {

Credential credential = authorize();

return new com.google.api.services.calendar.Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
}

private static void viewCalenders() throws IOException {

com.google.api.services.calendar.Calendar service = getCalendarService();

String pageToken = null;

do {
CalendarList calendarList = service.calendarList().list().setPageToken(pageToken).execute();
List&lt;CalendarListEntry&gt; items = calendarList.getItems();

for (CalendarListEntry calendarListEntry : items) {
System.out.println("viewCalenders()." + calendarListEntry.getSummary() + " --&gt; " + calendarListEntry.getId() + " --&gt; " + calendarListEntry.getAccessRole());
}

pageToken = calendarList.getNextPageToken();

} while (pageToken != null);

}

private static void insertEvent() throws IOException {

com.google.api.services.calendar.Calendar service = getCalendarService();

Event event = new Event()
.setSummary("Google I/O 2 2016/15")
.setLocation("800 Howard St., San Francisco, CA 94103")
.setDescription("A chance to hear more about Google's developer products.");

DateTime startDateTime = new DateTime("2015-12-15T09:00:00-07:00");

EventDateTime start = new EventDateTime()
.setDateTime(startDateTime)
.setTimeZone("America/Los_Angeles");

event.setStart(start);
DateTime endDateTime = new DateTime("2015-12-16T17:00:00-07:00");
EventDateTime end = new EventDateTime()
.setDateTime(endDateTime)
.setTimeZone("America/Los_Angeles");
event.setEnd(end);

String[] recurrence = new String[] {"RRULE:FREQ=DAILY;COUNT=2"};
event.setRecurrence(Arrays.asList(recurrence));
EventAttendee[] attendees = new EventAttendee[] {
new EventAttendee().setEmail("lwepage@example.com"),
new EventAttendee().setEmail("swebrin@example.com"),
};

event.setAttendees(Arrays.asList(attendees));
EventReminder[] reminderOverrides = new EventReminder[] {
new EventReminder().setMethod("email").setMinutes(24 * 60),
new EventReminder().setMethod("popup").setMinutes(10),
};

Event.Reminders reminders = new Event.Reminders()
.setUseDefault(false)
.setOverrides(Arrays.asList(reminderOverrides));

event.setReminders(reminders);

String calendarId = "primary";
event = service.events().insert(calendarId, event).execute();

System.out.printf("Event created: %s\n", event.getHtmlLink());

}

private static void viewEvents() throws IOException {

// Build a new authorized API client service.
// Note: Do not confuse this class with the
// com.google.api.services.calendar.model.Calendar class.

com.google.api.services.calendar.Calendar service = getCalendarService();

// List the next 10 events from the primary calendar.
DateTime now = new DateTime(System.currentTimeMillis());

Events events = service.events().list("primary")
.setMaxResults(10)
.setTimeMin(now)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute();

List&lt;Event&gt; items = events.getItems();

if (items.size() == 0) {
System.out.println("No upcoming events found.");
} else {
System.out.println("Upcoming events");
for (Event event : items) {
DateTime start = event.getStart().getDateTime();
if (start == null) {
start = event.getStart().getDate();
}

System.out.printf("%s (%s)\n", event.getSummary(), start);
}
}
}

public static void main(String[] args) throws IOException {
// viewCalenders();
viewEvents();
// insertEvent();
}

}

Dependencies :
You must download all the dependencies (eg : google client, google 0auth client etc) for this. There are 49 jars so far.
<dependencies>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.20.0</version>
</dependency>

<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-calendar</artifactId>
<version>v3-rev125-1.20.0</version>
</dependency>

<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.20.0</version>
</dependency>
</dependencies>

Here is the list of jars.

commons-cli-1.0.jar
commons-codec-1.3.jar
commons-lang-2.1.jar
commons-logging-1.1.1.jar
doxia-sink-api-1.0-alpha-7.jar
fit-google-calander-1.0.0.jar
google-api-client-1.20.0.jar
google-api-services-calendar-v3-rev125-1.20.0.jar
google-http-client-1.20.0.jar
google-http-client-jackson2-1.20.0.jar
google-oauth-client-1.20.0.jar
google-oauth-client-java6-1.20.0.jar
google-oauth-client-jetty-1.20.0.jar
guava-jdk5-13.0.jar
httpclient-4.0.1.jar
httpcore-4.0.1.jar
jackson-core-2.1.3.jar
jetty-6.1.26.jar
jetty-util-6.1.26.jar
jsr305-1.3.9.jar
junit-3.8.1.jar
maven-archiver-2.4.2.jar
maven-clean-plugin-2.4.1.jar
maven-common-artifact-filters-1.3.jar
maven-compiler-plugin-2.3.2.jar
maven-filtering-1.0.jar
maven-install-plugin-2.3.1.jar
maven-jar-plugin-2.3.2.jar
maven-reporting-api-2.0.6.jar
maven-reporting-api-2.0.9.jar
maven-resources-plugin-2.5.jar
maven-surefire-common-2.10.jar
maven-surefire-plugin-2.10.jar
plexus-archiver-2.0.1.jar
plexus-build-api-0.0.4.jar
plexus-compiler-api-1.8.1.jar
plexus-compiler-javac-1.8.1.jar
plexus-compiler-manager-1.8.1.jar
plexus-digest-1.0.jar
plexus-interactivity-api-1.0-alpha-4.jar
plexus-interpolation-1.13.jar
plexus-io-2.0.1.jar
plexus-utils-2.0.5.jar
plexus-utils-2.1.jar
plexus-utils-3.0.jar
servlet-api-2.5-20081211.jar
surefire-api-2.10.jar
surefire-booter-2.10.jar
surefire-junit3-2.10.jar

Here’s the interesting part – MY FINDINGS –

APPLICATION_NAME –
This should be the same name that you used for the OAuth 2.0 client ID.

DATA_STORE_DIR –
This is the directory where data (credentials etc) retrieved from the authorized users from the consent screen.

SCOPES –
There are two main scopes here.
1. CalendarScopes.CALENDAR : This is used to Manage the Calendar (Read, Insert, Delete, Update etc) data
2. CalendarScopes.CALENDAR_READONLY : This is used to only Read the Calender data
These scopes are very important when you grant the App permission from a user through the consent screen. It says you are asking the permission to Manage the Calendar or only Read the Calendar.
client_secret_1.0.0.json
This is the client secret that you have downloaded from the OAuth 2.0 client ID setup. This is Used to communicate with the Google App you have created as mentioned earlier. In this example it should be in the root folder. Anyway the path and name must be provided as below.

InputStream in = CalendarQuickstart.class.getResourceAsStream("/client_secret_1.0.0.json");

Grant the permission and credenials for a user.

Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("namal");

In this case when you are run the authorize method for the first time on each user (eg : namal as per .authorize(“namal”) ), iit will provide you a URL to display the consent screen

https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=123456789101-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com&redirect_uri=http://localhost:12345/Callback&response_type=code&scope=https://www.googleapis.com/auth/calendar

Then once run that on a browser you will be requested for permission for currently logged-in google account. If you haven’t logged-in yet you will be asked to log-in then will be requested for permission. Here, the consent screen contains the information you provided when you set-up it as mentioned earlier (eg : Developer’s email address, Product Name, Logo, URL for your site, Policies, Terms of Service, Permission you are requesting as mentioned in the SCOPE etc).

ConsentScreen

Then when you are Allowed, it will display the success message as mentioned below.

http://localhost:12345/Callback?code=1/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX#
Received verification code. You may now close this window…

Here, in this case, the credentials (of the google account used to allow the app) will be stored against the mentioned user (eg : “namal”) in DATA_STORE_DIR. So, you can use that user as the key to access the Google Calender (s) belongs to the Google account that allowed the app. This way you can manage Google Calender(s) of multiple Google Accounts using the keys.

View Calendar events

In this case, the Calender for the user’s email address will be mentioned as the “primary” one.

Events events = service.events().list("primary")
.setMaxResults(10)
.setTimeMin(now)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute();

You can specify the Calender ID -as mentioned in the viewCalenders() method- to obtain events in a perticular caleder. You can get this Calender ID from the Calendar Setting’s Calendar Address area.

Events events = service.events().list("xxxxxxxxxxxxxxxxxxxxxxxxxx@group.calendar.google.com")
.setMaxResults(10)
.setTimeMin(now)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute();

You can check the applications enabled for your google account via :
https://security.google.com/settings/security/permissions

References :

Written by Namal Fernando

December 15, 2015 at 6:48 am

Ruth's Reflections

Contemplations from quakey quirky Christchurch

TED Blog

The TED Blog shares interesting news about TED, TED Talks video, the TED Prize and more.

Ziplok

Learn and discover simple things

Meihta Dwiguna Saputra's Knowledge Base

~In learning you will teach and in teaching you will (re)learn~

The Java Blog

Thoughts, tips and tricks about the Java programming language

Sparkles

that were shone when I got tempered!