Saturday 28 June 2014

Java excel tutorial

Following is a simple excel sheet reading tutorial.

For this tutorial we will use the Apache POI library. This product is used to parse/write Micorsoft popular document formats, such as Excel, Power Point, etc., using Java. This is a common case for projects that need to produce reporting.

Prerequisites:
1) JDK installed
3) POI library from Apache
2) eclipse

If you do not have JDK, please download the lates stable release and install it:
http://www.oracle.com/technetwork/java/javase/downloads/index.html

Once you download it, just follow the instructions and keep the default installation.

Next is to get the POI library, which you can download from here:
http://poi.apache.org/download.html

Download the binary distribution and save it a location on your PC. I usually have a folder for Apache products, which I call "Apache", in there I keep all the downloaded pieces that wear its trend. Now extract the zip to the same folder. Here is the location I got:

C:\Apache\poi-3.10-FINAL

Now lets create a simple Excel sheet with one sheet in it:

I saved this sheet as "testBook.xlsx" under:

C:\Temp

Now we will create a Java project in eclipse, import required POI libraries, and write a simple class to parse this workbook.

1) Open your eclipse .If you do not have eclipse installed, download it from:
http://www.eclipse.org/downloads/ - I suggest to get the one for Java EE developers. Once you get it, open it up and create workspace. I have my workspace under:

C:\workspace

2) Choose a java perspective:


3) Create a java project. This can be done in several ways, but i usually just press Ctrl+N. Then in filter type java and click next:

I called the project ExcelParser:


Click finish.

Now we have an empty project. Lets place the POI libraries in this project.

1) Create a folder in your new project and call it lib (right-click on project and choose new --> folder):


call it lib.

Now we will copy all files required jar files from POI we downloaded into this lib folder (just use copy paste - programmer's best lucky move)

C:\Apache\poi-3.10-FINAL\poi-3.10-FINAL-20140208.jar
C:\Apache\poi-3.10-FINAL\poi-examples-3.10-FINAL-20140208.jar
C:\Apache\poi-3.10-FINAL\poi-excelant-3.10-FINAL-20140208.jar
C:\Apache\poi-3.10-FINAL\poi-ooxml-3.10-FINAL-20140208.jar
C:\Apache\poi-3.10-FINAL\poi-ooxml-schemas-3.10-FINAL-20140208.jar
C:\Apache\poi-3.10-FINAL\poi-scratchpad-3.10-FINAL-20140208.jar
C:\Apache\poi-3.10-FINAL\lib\commons-codec-1.5.jar
C:\Apache\poi-3.10-FINAL\lib\commons-logging-1.1.jar
C:\Apache\poi-3.10-FINAL\lib\junit-4.11.jar
C:\Apache\poi-3.10-FINAL\lib\log4j-1.2.13.jar
C:\Apache\poi-3.10-FINAL\ooxml-lib\dom4j-1.6.1.jar
C:\Apache\poi-3.10-FINAL\ooxml-lib\stax-api-1.0.1.jar
C:\Apache\poi-3.10-FINAL\ooxml-lib\xmlbeans-2.3.0.jar



Now we will add all these libraries to the classpath of the project so that our program may use them.
Right-click on the project ---> choose properties. Then on the left select Java Build Path and on the right click on libraries tab. Then click add jars button --> choose all the jars from the lib folder of our project and click ok, then ok on the build path:



Now we will create our Java program. For that we will need to create a package and a Java source file in it.

1) Right click on src folder and choose new --> package. I chose name as "com.test.processor".
2) Now lets create a parser class. Right click on a package and choose new -- > Class. I gave it a name of ExcelParser.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.test.processor;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelParser {

 public static void main(String[] args) {
  
  try {
   XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream("C:/Temp/testBook.xlsx"));
   
   // Get sheet.
   XSSFSheet sheet = wb.getSheetAt(0);
   
   for (int r = 0; r < sheet.getPhysicalNumberOfRows(); r++) {
    // Get row
    XSSFRow row = sheet.getRow(r);
    
    if (row == null) {
     continue;
    }
    
    // Parse cells
    for (int c = 0; c < row.getPhysicalNumberOfCells(); c ++) {
     
     XSSFCell cell = row.getCell(c);
     
     System.out.print(cell.getStringCellValue() + " | ");
     
    }
    
    System.out.println();
   }
   
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } 

 }

}

Now run your program.

Here is the output i got:


Username | First Name | Last Name | Depatment | Location | 
jmellow | Josh | Mellow | IT | New York | 
aspalleti | Adriano | Spalleti | IT | Rome | 
jsorrow1 | Jake | Sorrow | IT | Rome | 
jsorrow | Jake | Sorrow | QA | London | 
msmith | Mary | Smith | IT | London | 
tbrath | Tony | Brath | IT | New York | 
klindsay | Kate | Lindsay | IT | New York | 

Tuesday 17 June 2014

Несколько слов о паттернах в Java EE

Начал читать недавно одну книгу о паттернах в Java EE, как они изменились и "как нынче стоит составлять дизайн"! Хочу отметить что нынче паттерны звучат банально, на них не стоит утыкаться и зацикливаться как некоторые авторы этого негласно требуют, можно просто следовать обще принятым принципам таким как например, DRY (Do not repeat yourself), инкапсуляция, разделение обязанностей, в общем все то что ведет нас к выгодной позиции.

Анемическая модель доменов - раскритикована как ни знаю что. Тем не менее она проста и удобна. На мой взгляд, втыкать туда вспомогательные методы к примеру относящиеся только к этой сущности и ее дочерним коллекциям, и не определяя зависимости к внешним факторам а также принимая во внимание что поведение этих методов-аксессуаров возможно таким и останется - это нормально. Ограничимся этим. Выполнять там имплементацию Builder уже сомнительно, уже теряется простота, но все же можно если там нет бизнес логики. EnttyManager к сущности отношение не имеет, ему там сидеть тем более ни к чему. Анемическая модель после этого или нет - это не важно. Главное удобно и сущность не теряет своей эластичности. Сущность часто сильно зависит по своим свойствам от модели БД (трогать которую иногда нельзя), они сами по себе носят не самый доступный характер, но это значит только то что при возможности внося новшество JPA в систему нужно стремиться к упрощению.
К примеру, тут итак модель запутанна, добавлять туда бизнес логику не всегда разумно в особенности если она диктует порядок сохранения, и ее можно оставить за пределами сущности:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorValue("PFH.POINTABLE_SMBLOCK_TYPE")
public class GterPointableSmBlock extends GterSmall {

 @ManyToOne
 @JoinColumn(name="SMBLOCK_TYPE_ID_1")
 private PointableSmBlockType editableSmBlockType1;
 
 @ManyToOne
 @JoinColumn(name="SMBLOCK_TYPE_ID_2")
 private PointableSmBlockType editableSmBlockType2;
 
 @Column(name="ACTIVE")
 private int activeInd;
 
 @Column(name="AUDIT")
 private int auditNum;
 
 @Column(name="ROWSUID")
 private String rowId;
 
 @Column(name="CATSUID")
 private String cater;

Простенькие модельки, часто просто не в чем ином не нуждаются:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@Entity
public class User {
 
 @Id
 @GeneratedValue(strategy=GenerationType.AUTO)
 private long id;
 
 private String username;
 
 private String first;
 
 private String last;

 public long getId() {
  return id;
 }

 public void setId(long id) {
  this.id = id;
 }

 public String getUsername() {
  return username;
 }

 public void setUsername(String username) {
  this.username = username;
 }

 public String getFirst() {
  return first;
 }

 public void setFirst(String first) {
  this.first = first;
 }

 public String getLast() {
  return last;
 }

 public void setLast(String last) {
  this.last = last;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((first == null) ? 0 : first.hashCode());
  result = prime * result + ((last == null) ? 0 : last.hashCode());
  result = prime * result
    + ((username == null) ? 0 : username.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  User other = (User) obj;
  if (first == null) {
   if (other.first != null)
    return false;
  } else if (!first.equals(other.first))
   return false;
  if (last == null) {
   if (other.last != null)
    return false;
  } else if (!last.equals(other.last))
   return false;
  if (username == null) {
   if (other.username != null)
    return false;
  } else if (!username.equals(other.username))
   return false;
  return true;
 }
 
 

}

Такие паттерны как Service Facade, Service, вообще в принципе не несут сути в контексте Java EE. Сколько задач, столько и разновидностей, не может быть толкований на основе какой либо иной по мимо поставленной задачей производством и ее выполнения. Тем более о характеристиках таких как TransactionAttribute. Все очень индивидуально, просто раньше технология J2EE несла кучу недоработок, в обход которым были созданы продукты прогресса такие как DI (Dependency Injection), упрощенные EJB и паттерны уже как таковые ни чего не значат. Девелопер уже может больше времени уделять разработке бизнес логики с использованием полиморфизма как метод элегантной обрисовки процесса и.т.д, нежели заниматься демагогией о паттернах в сфере EE.     

Sunday 15 June 2014

Учебное пособие struts2 на сервере Weblogic 10.3


Struts 2 – Weblogic 10.3.4 туториал.

Этот туториял, как то давно писал на английском, решил перевести на русский

Вот что нужно предварительно:
1 ) JDK 6
2) eclipse
3) weblogic server 10.3.4 or later
4) Ant 6

1)     Загрузите последний релиз struts 2 (http://struts.apache.org/).
2)     Распакуйте struts в какое нибудь вам приемлемое место к которому бедем оброщаться как к STRUTS_HOME.
3)     Создайте новый java проэкт в эклипсе и назовите его как вам нравиться ну а мы тут назовем его strutsApp. 








4)     Теперь разработаем build файл, который будет собирать части приложения в единый war архив. Вот этот build файл который я вытащил из другого проэкта и подкоректировал под наш (на дату внимания не обращайте )):


<?xml version="1.0" encoding="UTF-8"?>
<!-- ======================================================================
     Aug 21, 2011 11:58:33 AM                                                        

     This is our struts project.
                  
     iakoupov                                                               
     ====================================================================== -->
<project name="strutsApp" default="war" basedir=".">
    <description>
            This is the struts project.
    </description>
      
       <property name="wl.autodeploy.dir" value="C:\oracle\Middleware\user_projects\domains\strutsApp\autodeploy"/>
       <property name="strutsApp.war.name" value="strutsApp.war"/>
       <property name="strutsApp.ejb.name" value="strutsAppEJB.jar"/>


       <path id="war.classpath">
              <fileset dir="./WEB-INF/lib">
                     <include name="**/*.jar"/>
              </fileset>
             
              <fileset dir="C:\oracle\Middleware\wlserver_10.3\server\lib">
                     <include name="weblogic.jar"/>
              </fileset>
       </path>
      
       <path id="ejb.classpath">
                    
              <fileset dir="C:\oracle\Middleware\user_projects\domains\strutsApp\lib">
                     <include name="**/*.jar"/>
              </fileset>
      
              <fileset dir="C:\oracle\Middleware\wlserver_10.3\server\lib">
                     <include name="**/*.jar"/>
              </fileset>
             
              <fileset dir="C:\oracle\Middleware\modules">
                     <include name="javax.ejb_3.0.1.jar"/>
                     <include name="javax.jms_1.1.1.jar"/>
              </fileset>
       </path>

    <!-- =================================
          target: war             
         ================================= -->
    <target name="war" depends="" description="This is a struts project.">
      
      
       <antcall target="mkdirs"/>
        <antcall target="compileWar"/>
      
       <war destfile="${wl.autodeploy.dir}\${strutsApp.war.name}"
              webxml="./WEB-INF/web.xml">
              <classes dir="./classes"/>
              <lib dir="./WEB-INF/lib"/>
       </war>
      
      
    </target>
      
       <!-- =================================
                 target: EJB             
                ================================= -->
           <target name="ejb" depends="" description="">
             
             
              <antcall target="mkdirs"/>
               <antcall target="compileEJBs"/>
             
              <jar
                     destfile="${wl.autodeploy.dir}\${strutsApp.ejb.name}"
                     basedir="./classes">
                    
              </jar>
             
           </target>
      
       <target name="mkdirs" description="Creates required directories for compiation">
              <delete dir="./compile"/>
       <delete dir="./classes"/>
       <mkdir dir="./compile"/>
       <mkdir dir="./classes"/>
       </target>
      
       <!-- - - - - - - - - - - - - - - - - -
                 target: compileEJBs                     
                - - - - - - - - - - - - - - - - - -->
           <target name="compileEJBs">
              <javac srcdir="./src"
                     destdir="./classes"
                     classpathref="ejb.classpath"
                     debug="true" debuglevel="lines,vars,source">
                    
              </javac>
             
              <copy todir="./classes">
                  <fileset dir="src"
                           includes="**/*.properties" />
              </copy>
             
           </target>

    <!-- - - - - - - - - - - - - - - - - -
          target: compile                     
         - - - - - - - - - - - - - - - - - -->
    <target name="compileWar">
       <javac srcdir="./src"
              destdir="./classes"
              classpathref="war.classpath"
              debug="true" debuglevel="lines,vars,source">
             
       </javac>
      
       <copy todir="./classes">
           <fileset dir="src"
                    includes="**/*.xsl" />
       </copy>
    </target>

</project>
5)     Обратите внимание на autodeploy директорию, она указывает место расположения домена веблоджика. Если у вас есть какой нибудь домен, то можете указать его, если нет то следующий шаг рассказывает как таковой создать.

6)     Откойте weblogic configuration wizard. Выберете create new domain. Если хотите, выберете дополнительную опцию установки Web services ( я выбрал jax-ws extension, хот и нам это ни к чему но вот в бедещем...). Назовите домен как хотите, мы же для простоты назовем его strutsApp. Выберете user/passwords для консоля и запомните, лучше записать. Выберете JDK. Отметьте AdministrationServer. Выберете порт, удостоверившись что другие сервера на нем не бегут, вроде по умолчанию там 7001. Затем next и done.

7)    Теперь, чтоб не усложнять себе жизнь и не делать чего то с нуля, возьмем готовую програмку struts2 которая идет вместе с загрузкой библиотек struts 2 в качестве примера. Зайдите в STRUTS_HOME\apps. Распакуйте struts2-blank.war в той же папке. Я распаковал этот пример в папку struts2-blank, директории STRUTS_HOME\apps, то есть в STRUTS_HOME\apps\struts2-blank.

8)     В проэкте еклипса создайте папку Web-INF. Внутри “WEB-INF” другую и назовите ее “lib”. теперь в этот lib скопируйте все библиотеки из STRUTS_HOME\apps\struts2-blank\WEB-INF\lib.     

9)     Теперь давайте скопируем все нужные нам файлы из этой программы. План таков, чтобы построить проэкт из иcходного кода стратсовского примера, и после того как процесс формирования программы будет отлажен ничиная с исходников и заканчивая рабочим приложением, в будущем можно будет с легкостью вносить изменения, так как подготовка всегда занимает больше времени нежели сама разработка, а так-же вносить изменения всегда почти легче нежели писать с нуля (я не говорю о тех программах которые огромны но безнадежно запоренны изначально, в током случае может быть проще выкинуть и перписать по человечески, но это утопия так как начальство смотрит на вещи не всегда с перспективой кагого то будушего). Итак не будем распускать нюно-философию и вернемся к поставленной задаче. Скопирейте папку example в корень эклипс-проэкта, затем error и index jsps странички тоже туда, а вот web.xml из web-inf в web-inf проэкта, теперь скопируйте example.xml и struts.xml из src\java в папку src вашего проэкта. Теперь в папке src создайте новый package с названием example и скопируйте туда файлы из src\java\example. То есть мы просто передвигаем исходники в наш проэкт таким образом чтоб исходники не пришлось менять, это мы на потом оставим, на ваше усмотрение. Должно появиться куча ошибок компилирования, это из за того что исходники не находят для компеляции нужных им библиотек, ну вот мы им на них и укажем. Нажмите правой кнопкой мышки на проэкт и выберете properties, слева нажмите не Java Build Path, затем нажмите на таб libraries, затем нажмите на кнопку add jars справа (щас мы выберем необходимые для компеляции библиотеки), выберете свой проэкт затем web-inf а в нем lib и отметьте там все jar файлы. Нажмите там ok и все ошибки должны исчезнуть.
10)    Я повторяю, идея состоит в том что-бы запустить этот пример. Пришлось внести некоторые изменения в build.xml, по двум таргетам:


















<target name="war" depends="" description="This is a struts project.">
     
     
      <antcall target="mkdirs"/>
        <antcall target="compileWar"/>
     
      <war destfile="${wl.autodeploy.dir}\${strutsApp.war.name}"
            webxml="./WEB-INF/web.xml">
            <classes dir="./classes"/>
            <lib dir="./WEB-INF/lib"/>
            <fileset dir="."
               includes="**/*.jsp" />
                       
             <fileset dir="."
                  includes="**/*.html" />
                       
             <fileset dir="."
                  includes="**/*.xhtml" />
      </war>
     
     
    </target>
<target name="compileWar">
      <javac srcdir="./src"
            destdir="./classes"
            classpathref="war.classpath"
            debug="true" debuglevel="lines,vars,source">
           
      </javac>
     
      <copy todir="./classes">
          <fileset dir="src"
                   includes="**/*.xsl" />
           
            <fileset dir="src"
                   includes="**/*.xml" />
           
            <fileset dir="src"
                  includes="**/*.properties" />
      </copy>
</target>




11)  Запускаем build файл! При запуске, выберете target WAR. После удачног запуска, проверьте директорию autodeploy в домене вашего Weblogic-а. Вот директория, которую я проверял у себя: C:\oracle\Middleware\wlserver10.3\user_projects\domains\strutsApp\autodeploy тут должел быть ваш WAR архив. Открйте и проверьте что-бы все было на месте, в правильных папках и.т.д:







12)  Запустите Weblogic (в вашем домене есть папка bin и в нутри нее, startWeblogic.cmd и такой-же файл с .sh екстеншеном, если вы в винде то вам нежен cmd). После запуска вы должны увидеть log4j info записи в консоле эклклипса - это если вы сервер запускаете из эклипса (или в окне cmd если так).


13)  В браузере зайдите по адресу http://localhost:7002/strutsApp. У меня порт 7002, вы укажите свой. Заметьте что название WAR архива служит директорией адреса, это обычно всегда так. Вот что вы должны увидеть, и если вы это видете то запуск удался: struts is up and running. Hooray!