понеділок, 5 жовтня 2015 р.

Free Book: Java: The Legend

Java: The Legend
Past, Present, and Future
Publisher: O'Reilly
Released: September 2015
The road from Java's first public alpha of 1.0 to today has been long—and full of technical advances, innovative solutions, and interesting complications. Along the way, Java has flourished and is now one of the world's most important and widely-used programming environments.

Benjamin Evans, the Java editor for InfoQ and author of Java in a Nutshell, 6th edition, takes us on a journey through time:

- How Java has benefitted from early design decisions, including "Write Once, Run Anywhere" and an insistence on backward compatibility- The impact of open source- The enormous success and continued importance of the Java Virtual Machine and platform- The rise of Enterprise Java- The evolution of the Java developer community and ecosystem- Java's continuing influence on new programming languages- Java's greatest triumphs and most heroic failures- The future of Java, including Java 9, Project Panama, Project Valhalla, and the Internet of Things

Request Book

пʼятниця, 2 жовтня 2015 р.

Want to design a t-shirt for JavaOne?

Cross Your Tees_Hori_v2.jpg

Want to design a t-shirt for JavaOne? To celebrate 20 years of Java, we’re inviting you to submit t-shirt designs. The winning design will be one of the available options at the Cross Your Tees experience, taking place all week long during JavaOne 2015 at the Parc 55 San Francisco.
Attendees will have the opportunity to choose from four different designs to create their custom shirt, and one of those designs could be yours!!
Submit your design by Wednesday: October 7th at 12:00pm! 

Artwork Specifications:
Designs submitted must incorporate the evolution of Java over the last twenty years. Artwork submitted for the t-shirt design must be no longer than 12” w and 14” h and adhere to the following specifications:
• AI File Type
·          Layers Preserved
·          Fonts Outlined
·          White or Blank Artboard
·          PMS colors (if needed)
• PDF File Type
·          > 300 dpi
·          100% scale
·          Include all font types
·          White Background
·          PMS colors (if needed)
Check out the challenge details and official rules Submit today! 
Looking forward to seeing your designs.
Erica Morales | Event Manager Oracle Global Events
10 Twin Dolphin Drive, Redwood Shores, CA 94065

JUG Meetup "Silicon Valley approach to building powerful PaaS"

JUG Lviv Meetup

We are delighted to invite you to a JUG Meetup. 
This time, we are hosting a really special event, with exceptional speakers and a fabulous venue.
The meetpu is supported by SoftBistro and Chegg.
Date: 15th of October.


Silicon Valley approach to building powerful PaaS

Presentation abstract:

Learn an innovative approach to back-end service development via an internal PaaS, which is both delightful for customers and pleasant to work with for engineers.

Geared towards Senior Java developers,  the talk has a strong emphasis on architecture. It will cover highly modular, meta-data driven development, used to address some of the most challenging problems of building distributed systems. The audience will explore ways of leveraging OSGi, Fluent Java APIs, with a model driven approach to gain developer and operational efficiency.


Jason Schnitzer, CTO, Chegg

Ashit Joshi, VP of Engineering, Chegg


Thursday, October 15th
18:45 - 19:00 Welcome coffee 
19:00 - 19:55 Silicon Valley approach to building powerful PaaS
19:55 - 20:05 - Company culture discussion
20:05 - 21:00 - Informal discussion and dinner


The meetup will be hosted at Rius - newly built hotel, right at the city center.
Hotel RIUS
Conference room (2 поверх)
Akademika Hnatyuka St, 12А 


SoftBistro is a software development company delivering services for partners in the Silicon Valley. SoftBistro operates two development centers in Lviv and Khmelnytsky Ukraine. Although we love building products for the higher-ed market, we also have served a broad range of partners across many markets and industries. From start-ups in Silicon Valley, such as BigStock and Rafter to publicly traded Chegg, ShutterStock and Freelancer. For further information, please visit:

Chegg, Inc is a student-first connected learning platform.  We are publicly-held company based in Santa Clara, California that trades on the NYSE under the symbol CHGG. As the leading connected learning platform, Chegg’s Student Hub makes higher education more affordable and more accessible, while improving student outcomes. Chegg puts students first and is proud to have saved students and their families more than $450 million in 2015 alone. For further information, please visit:


The event is completely free, however, the number of attendees is strictly limited, thus, we do require registration.
Please also note, the event will be targeting experienced engineers and architects.

Registration form is here.

пʼятниця, 25 вересня 2015 р.

XP Injection invitation and discount code

We are more than happy to invite you to XP Days Ukraine – a conference purely devoted to Agile engineering practices! The program committee, including our friend Taras Matyashovsky from Lohika, did their best to impress the participants with new foreign names in speakers list as well as experienced guys from all over Ukraine. Among them are: Venkat Subramaniam, Paul Stack, Viktor Farcic, Jon Jagger and many others.
For current version of the agenda visit

What is interesting this year?
The program committee decided to concentrate on following topics:
  • All-level automation, including infrastructure, testing, deployment, etc.
  • Approaches to architecture and design in Agile processes
  • Continuous Delivery as ultimate goal for almost every product
  • Scaling, microservises and containerization – today you can hardly imagine modern development without them. 
Also, our friends from Morning@Lohika community were granted a 10% discount promo code “Morning@Lohika”. But it can be used 10 times only.
See you on 23rd – 24th of October in Kyiv!

середа, 19 серпня 2015 р.

Spring training in Lviv!

We are glad to inform you, that Evgeny Borisov will have two days training in Lviv!

Evgeny is well-known speaker (, - JEEConf, Joker, JavaDay Kiev, JavaDay Lviv) and trainer from Israel.
Since 2001 Evgeny was working as Java Developer, Team Leader, Java Architect and Java Trainer. Today he works at JFrog and has his own consulting company.
Two days training fully dedicated to Design Patterns and Deep Dive into Spring Framework will be held on 2nd - 3rd of October at Lohika office. For more detailed information about agenda and schedule please refer to

For JUG & Morning@Lohika friends we have 5 promo codes (please enter Morning@Lohika) with 200UAH discount.

Also, Evgeny will share with us one of his presentation at Morning@Lohika that will be held 3rd of October, and will be free. Please, watch for news here and don`t miss the event!

четвер, 13 серпня 2015 р.

АОР & Performance tool

Що спільного в словах AOP та Performance tool ? -нічого , окрім того що задопомогою АОР ми будемо пиляти власного "валосипеда" і спробуємо ним поміря швидкодію Java аплікацій.

Отож, визначимо цілі нашого проекту :

  • Отримаувати заміри виконання методі задопомогою анотацій
  • Керувати історією викликів мотода
  • Отримувати результат в наступних форматах : String, JSON, HTML
Проект унас буде збиратися Apache Maven'ом, для імплементації АОР використаємо AspectJ а тести напишемо на JUnit.

Отже, створюємо наш проект командою : "mvn archetype:create  -DartifactId=Stat4J" з цього бидно архітектуру пакетів а також горду назву "Stat4J" (типу заявка на світове визнання 8-D ).

Додаємо залежності в pom.xml :



Створюємо пакет "" і додаємо в в нього клас "", це і буде наша анотація котру ставитимемо над методом котрий будемо заміряти. Відкриваємо клас і пишемо в ньому настйпний код :

public @interface Stat4JPoint {

@Target - місце над яким можна буде декларувати дану анотацію , у нашому випадку це методи.
@Retention - як довго дана анотація буде зберігатися над анотованим типом, у нашому випадку напротязі усього виконання аплікації.
@interface - вказує що даний клас є анотацією

Отже тепер ми маємо анотацію яка буде вказувати на методи котрі нам треба заміряти, залишилось тільки відслідковувати коли під час виконання аплікацію будуть викликатися анотовані цією анотацією методи. Для цього нам і потрібне АОР.

Створюємо пакет "" і додаємо туди наш аспект "Stat4JAsp.aj". Даний аспект повинен спрацьовувати коли буде викликано будь який метод анотований нашою анотацією. Для цього в середену аспекту пишемо :

@Aspectpublic class Stat4JAsp 

 @Around("execution(* *(..)) &&@annotation(")  public Object around(ProceedingJoinPoint point) throws Throwable {



@Aspect - вказує AspectJ плагіну (який ми пізніше додато до конфігурації мавена) , що даний клас є аспектом.
@Around - вказує що даний аспект має виконатись навколо методу , тобто не перед чи після а саме навко методу (іншими словами його обгортаємо) а як аргумент ми передаємо умову при якій даний аспект повинен виконатись : * - будь який ретурн тип , * - будь яка назва методу , (..) - будь яка кількість аргументів,  && - а також , @annotation(<type>) - анотація типу <type>.

Тепер у нас є анотація і аспект який її відслідковуватиме.

Залишилось лише додати плагін до bild секції в pom.xml який під час компіляції проекту зробить всю ту "магію" яка називається АОР (Обгорне анотовані методи своєю іпмлементацією). Плагін має виглядати так :

        <goal>compile</goal><!-- to weave all your main classes -->
        <goal>test-compile</goal><!-- to weave all your test classes --> 

В даній конфігурації важливо вірно вказати пакет в якому знаходяться ваші аспекти а також версію джави (у нашому випадку 1.8).

Пробуємо білдати наш проект : mvn clean install , і якщо бачимо :

[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------

тоді усе гаразд. 

Тепер давайте зробимо власне нашу утиліту яка буде відповідати за початок заміру, кінець а також вивід статистики. Створюємо в пакеті "" класс і зробимо його синглтоном щоб там де він буде використовуватись він завжди був єдиним на всю систему.

public class Stat4J { 
  private static Stat4J instance;
  private Stat4J() {} 
  public static Stat4J instance() { 
    if (instance == null) { 
      synchronized (Stat4J.class) { 
        if (instance == null) { 
          instance = new Stat4J();
    return instance;

Тепер, маючи головний клас нашої утиліти створюємо пакет "" і додаємо два класи , перший для зберігання усієї статистики , а другий для зберігання статистики конкретно по одному виклику метода :

public class Statistic { 
  private List<Point> stats = new ArrayList<>();

public class Point implements Comparable<Point>{ 
  public static final int NANO_IN_MILIS = 1000000;
  private long startTrack;
  private long finishTrack;

Тепер навчимо клас обраховувати інформацію про свої заміри :

(приклад наводжу на одному з методів, повна версія буде доступна за посилання в кінці поста)

public long getMaxExecutionTimeInNano(){ 
  if(!stats.isEmpty()) { 
    return stats.get(stats.size()-1).executionTimeInNanoseconds();
  return 0;

Маючи об'єкт статистики і всю інформацію про виклики методу додамо мапу в головний об'єкт нашої утиліти котра за іменем класу зберігатиме іншу мапу , яка в свою чергу за іменем методу зберігатиме об'єкт статистики :

private Map<String, Map<String, Statistic>> records;

Також додаємо метод який розпочинатиме та закічнуватиме заміри :

public Point startTrack(String componentName, String pointName) { 
  Point point = new Point(System.nanoTime());
  if (!records.containsKey(componentName)) { 
    Statistic statistic = new Statistic();
    Map<String, Statistic> pointToStat = new HashMap<>();
    pointToStat.put(pointName, statistic);
    records.put(componentName, pointToStat);
  } else if (!records.get(componentName).containsKey(pointName)) {
    Statistic statistic = new Statistic();
    records.get(componentName).put(pointName, statistic);
  } else {
  return point;
Перший if ініціалізує цілу групу замірів відштовхуєчись від імені класу. Другий if інішіалізує групу замірів на базі методів у випадку якщо група класу вже ініціалізована. А третій if спрацює якщо група класу і методі уже є , тоді тільки додасть новий замір.

public void stopTrack(Point point) { 

Для зупинки заміру просто проставляємо поточну дату (час закінчення) в точку заміру .

Маючи все вище написане залишаться оновити наш аспект і в його тілі вказати що перш ніж виконати метод ми повинні розпочати замір а далі виконати метод і після цього закінчити замір:

Point statisticPoint =   Stat4J.instance().startTrack(point.getTarget().getClass().getCanonicalName(), MethodSignature.class.cast(point.getSignature()).getMethod().getName());

Object result = point.proceed();

return result;

У випадку якщо наш метод нічого не повертає , ми всеодно повинні повертати Object як результат виконання методу так як на даному етапі аспект нічого про сам метод не знає.

Компілюємо аплікацію і впевнюємось що унас все зроблено вірно.

Залишилось вивестинаш результат. Для цього створюємо пакет "" і додаємо в нього клас "StringPriner,java". Він повинен приймати наші об"єкти статистики та примати аргументом параметр що буде вказувати треба нам історія викликів методу чи ні . 

Ось код цього прінтера : 

public class StringPrinter implements Printer{

  public static final String COMPONENT_OUTPUT = "%1s.%2s:\tCall times: %3s,\tMax:     %4s (ns)\t|\t%5s(ms),\tMin: %6s(ns)\t|\t%7s(ms),\tAvr: %8s(ns)\t|\t%9s(ms);\n";

  public static final String POINT_OUTPUT = "\t\t%1s:\tExecution date:  
  %2s,\tExecution time: %3s\t(ns)|\t%4s(ms);\n";

  public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM.dd.yy   HH:mm:ss.SSS");

  public String print(Map<String, Map<String, Statistic>> statistic, boolean history){
    final StringBuilder strBld = new StringBuilder();

    statistic.forEach((componentName, points) -> points.forEach((pointName, stats) 
    -> strBld.append(generateComponentStatistic(componentName, pointName, stats,

   return strBld.toString();

  private String generateComponentStatistic(String componentName, String pointName,   Statistic statistic, boolean history) {

    StringBuilder strBld = new StringBuilder(); 
    strBld.append(String.format(COMPONENT_OUTPUT, componentName, pointName,
    statistic.getPointSize(), statistic.getMaxExecutionTimeInNano(),
    if (history && statistic.getPoints().size() > 1) { 
      statistic.getPoints().forEach((statPoint) ->
    return strBld.toString(); 
Тепер потрібно додати метод в головний клас утиліти для виводу статистики який буде приймати аргументом тип прінтера (String, JSON, HTML) і вмикання / вимикання історії викликів :

private final StringPrinter stringPrinter = new StringPrinter();
  public String getStatistic(OutputFormatType outputFormatType, boolean history){ 
      case STRING: return stringPrinter.print(records,history);
Після цього напишемо тестовий склас  методи якого нічого не робитимуть але зупинятимуть потік на якийсь час, і заанотуємо ці методи щоб виміряти їх час виконання :

public class PerformanceTestObject {
  public void method2MS() throws InterruptedException { 
  public void method25MS() throws InterruptedException {
  public int method155MS() throws InterruptedException { 
    return 155;
  public void method1Sec() throws InterruptedException { 

і відповідно сам тест :

public class Point4JAspTest { 
  public void testPerformanceMeassuringStringOutput() throws InterruptedException {     PerformanceTestObject performanceTestObject = new PerformanceTestObject();     

Запускаємо та дивимось результат : Call times:   4, Max: 30011694(ns) |   30(ms), Min: 27759291(ns) |     27(ms), Avr: 28949879(ns) |       28(ms);
method25MS: Execution date: 03.03.76 14:58:04.321, Execution time: 27759291 (ns)|  27(ms);
method25MS: Execution date: 03.03.76 07:00:38.850, Execution time: 28609810 (ns)|  28(ms);
method25MS: Execution date: 03.02.76 14:27:54.968, Execution time: 29418723 (ns)|  29(ms);
method25MS: Execution date: 03.02.76 22:38:51.322, Execution time: 30011694 (ns)|  30(ms); Call times:   1, Max: 3253797(ns) |    3(ms), Min: 3253797(ns) |      3(ms), Avr:  3253797(ns) |        3(ms); Call times:   1, Max: 1002833335(ns) | 1002(ms), Min: 1002833335(ns) |   1002(ms), Avr: 1002833335(ns) |     1002(ms); Call times:   1, Max: 162245276(ns) |  162(ms), Min: 162245276(ns) |    162(ms), Avr: 162245276(ns) |      162(ms);

Ось і все. Прінтери для JSON та HTML формату не став тут викладати заради економії часу проте все чого тут не вистачає ви зможене знайти тут.

Очікую ваші відгуки та пропозиції щодо даної утиліти.

П.С. Надіюсь було цікаво.