Sparkles

that were shone when I got tempered!

Archive for the ‘Java’ Category

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 

 

Advertisements

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

Flexibility of static factory methods in JDBC

leave a comment »

JDBC – Java Data Base Connectivity API – is a Service Provider Framework.

Class of the object returned by the static factory method not even need to be existed when that factory method is written. This kind of flexibility generates the basis of a Service Provider Framework (like JDBC – Java Data Base Connectivity API).

In a Service Provider Framework, multiple Service Providers implement services. And there are clients that is willing to use it. Service Provider Framework make this Service Provider’s implementation available to the clients decoupling the implementation from them.

There are three essential components of a service provider framework.

  1. Service Interface – which providers implement
  2. Provider Registration API – which the system provides to register the implemenetations and clients to access to them.
  3. Service Access API – which the clients use to obtain an instance of the service.
    When the clients don’t specify the criteria to choose a provider, Service Access API returns a default implementation. Here, the service access API plays as a “flexible static factory”.

There’s an optional fourth component also. It is Service Provide Interface which providers implement to create the instance of their service implementation. In the absence of the service provider interface implementations are registered by the class names and instantiated reflectively.

In the case of JDBC,

  • Connection plays the part of the Service Interface,
  • DriverManager.registerDriver is the Provider Registration API,
  • DriverManager.getConnection is the Service Access API, and
  • Driver is the Service Provider Interface.

There are numerous variants of the Service Provider Framework Pattern. For example, the Service Access API can return a richer service interface than the one required of the provider, using the Adapter Pattern.

//Service provider framework sketch
//Service interface
public interface Service {
	... // Service-specific methods go here
}

//Service provider interface
public interface Provider {
	Service newService();
}

//Noninstantiable class for service registration and access
public class Services {
	
	private Services() { } // Prevents instantiation (Item 4)
	
	//Maps service names to services
	private static final Map&lt;String, Provider&gt; providers =
			new ConcurrentHashMap&lt;String, Provider&gt;();
	
	public static final String DEFAULT_PROVIDER_NAME = &quot;&lt;def&gt;&quot;;
	
	//Provider registration API
	public static void registerDefaultProvider(Provider p) {
		registerProvider(DEFAULT_PROVIDER_NAME, p);
	}
	
	public static void registerProvider(String name, Provider p){
		providers.put(name, p);
	}
	
	//Service access API
	public static Service newInstance() {
		return newInstance(DEFAULT_PROVIDER_NAME);
	}
	
	public static Service newInstance(String name) {
		Provider p = providers.get(name);
		if (p == null)
			throw new IllegalArgumentException(
					&quot;No provider registered with name: &quot; + name);
		return p.newService();
	}
	
}
}


Reference :

  • Effective Java TM – Second Edition by Joshua Bloch

Written by Namal Fernando

April 17, 2015 at 8:39 am

Posted in Java

Tagged with ,

Sorting Collections in Java

leave a comment »

Sorting an ArrayList of Strings alphabetically.

This is pretty simple with the Collection.sort() as follows.

package collections.sorting;

import java.util.*;

class TestSort1 {

	public static void main(String[] args) {
		
		ArrayList<String> 	stuff 	= new ArrayList<String>();
		stuff.add("Denver");
		stuff.add("Boulder");
		stuff.add("Vail");
		stuff.add("Aspen");
		stuff.add("Telluride");
		
		System.out.println("unsorted " + stuff);
		
		Collections.sort(stuff);
		System.out.println("sorted" + stuff);
	}
	
}

This prints
unsorted [Denver, Boulder, Vail, Aspen, Telluride]
sorted [Aspen, Boulder, Denver, Telluride, Vail]

Sorting an ArrayList of — we created — DVDInfos.

DVDInfo.java


package collections.sorting.dvdInfo;

class DVDInfo {
	
	String title;
	String genre;
	String leadActor;
	
	DVDInfo(String t, String g, String a) {

		title = t; genre = g; leadActor = a;
	}
	
	public String toString() {
		return title + " " + genre + " " + leadActor + "\n";
	}

}

In another client class,

</pre>
ArrayList<DVDInfo> dvdInfoList = new ArrayList<DVDInfo>();
Collections.sort(dvdInfoList);

Throws an error –
Bound mismatch: The generic method sort(List<T>) of type Collections is not applicable for the arguments (ArrayList<DVDInfo>). The inferred type DVDInfo is not a valid substitute for the bounded parameter <T extends Comparable<? super T>>.

Reason –
The sort() method takes a List argument, and that the objects in the List must implement an interface called Comparable. It turns out that String implements Comparable, and that’s why we were able to sort a list of Strings using the Collections.sort() method.

 

The Comparable Interface

The Comparable interface is used by the Collections.sort() method and the java.util.Arrays.sort() method to sort Lists and arrays of objects, respectively. To implement Comparable , a class must implement a single method,compareTo() .

Here’s an invocation of compareTo() :

</pre>
int x = thisObject.compareTo(anotherObject);

The compareTo() method returns an int with the following characteristics:

  • negative : If thisObject < anotherObject
  • zero : If thisObject == anotherObject
  • positive : If thisObject > anotherObject

So, we can change the DVDInfo.java class like this to make it comparable

package collections.sorting.dvdInfo;

class DVDInfo implements Comparable<DVDInfo>{

	DVDInfo(String t, String g, String a) {
		
		title = t; genre = g; leadActor = a;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String toString() {
		return title + " " + genre + " " + leadActor + "\n";
	}

	public int compareTo(DVDInfo d) {
		return title.compareTo(d.getTitle());
	}

	String title;
	String genre;
	String leadActor;

}

This actually makes it comparable.
But, we’ll probably want to sort DVD collections in lots of different ways. Since we sorted our ArrayList by implementing the compareTo() method, we seem to be stuck. So, there must be another way to do this – which is comming up next – .

Sorting with Comparator

The Comparator interface gives you the capability to sort a given collection any number of different ways. The other handy thing about the Comparator interface is that you can use it to sort instances of any class—even classes you can’t modify —unlike the Comparable interface, which forces you to change the class whose instances you want to sort. The Comparator interface is also very easy to implement, having only one method, compare() . Here’s a small class that can be used to sort a List of DVDInfo instances, by genre

class GenreSort implements Comparator<DVDInfo> {

	public int compare(DVDInfo one, DVDInfo two) {
	
		return one.getGenre().compareTo(two.getGenre());
	
	}

}

So, now we can sort it without touching DVDInfo class (to implemnet the Comparable and override compareTo method in there) like follows.

GenreSort genreSort = new GenreSort();
Collections.sort(dvdInfoList, genreSort);

Screenshot from 2015-04-15 14:19:54Reference :

  • SCJP

Written by Namal Fernando

April 15, 2015 at 2:17 pm

Posted in Java

Tagged with ,

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!