Tuesday 26 August 2014

Java EE - что это, ее неполное составляющее.

Java EE


В нынешние времена считается что та система хороша, которая надежна как топор, быстра как молния, независима как ветер, проста как валенок и продуктивна в разработке как паровоз. Java EE в свою очередь, выполняет достаточно много из таких требований, конечно с определенной корректировкой на реальность. Реальность такова что больше и больше энтерпрайзов начинают сотрудничать с друг другом, так-как понимают что вместе можно слепить больше и продать быстрее - это как единый организм с независимыми частями, каждая выполняющая свою функцию и пользующаяся плодами других, главное тут конечно не путать кто чем должен заниматься. Так вот все это, предприятия будут стараться поддерживать на уровне ПО. Тут Java EE хороша как раз своей мобильностью, сетью готовых разработок (API), полноценной поддержкой транзакций во многих сферах подразделений, а так-же набором готовых продуктов для обеспечения безопасности и надежности. Скорость конечно не самая лучшая, тем не менее нужных результатов добиться в основном можно. Простота за счет постоянного стремительного развития ООП (объектно ориентированного программирования) в Java EE легко уже достигается, хоть и увеличилась информационная база значительно за последние годы. Разработка Java EE закреплена спецификациями, большинство, если не всё, из которых поддерживается разными серверами. На чем уж действительно можно сделать акцент, та это на том что разработка с Java EE действительно продуктивна и проста из за огромной базы функционала, который свободно можно внедрить, сконфигурировать и он будет взаимодействовать под эгидой ООП. В основном крупные системы многослойны и включают в себя кучу всего. Такой распорядок определяет эффективную организацию большого предприятия. Вот что примерно их себя представляет архитектура типичной Java EE системы.

Diagram of multitiered application structure, including client tier, web tier, business tier, and EIS tier.

Клиент, это пользователь с браузером. Связь может осуществляться через компьютер, телефон или любой инструмент располагающий каким-нибудь типом связи.

Java EE Server

Java EE сервер, состоит из множества частей, наиболее весомые это EJBs, они обычно используются для выполнения бизнес логики в так называемом business tier. А вот то что обеспечивает связь с клиентом через например http протокол, так это какой-нибудь фреймворк такой например как JSF, хотя это может быть и Struts и все что угодно; именуется этот слой как front end или Web tier. Главное что обычно есть хоть и небольшое и не всегда вполне ощущаемое разделение между web и business слоем. Зачастую business слой ответственен за подсоединение с базой данных (БД), хотя опять-же если нет особого разделения между web и business, то можно сказать что web так-же обеспечен возможностью соединения.

Web Tier

Этот слой состоит из страниц и технологий способных их обрабатывать. Это все то, что может обрабатываться Web контейнером (считается что Java EE сервер содержит в себе Web Container для этого слоя. Например раньше JBoss содержал в себе Tomcat, потом разработал свой модуль). Это могут быть HTML файлы с CSS и JavaScript. Используются так-же файлы типа JSP которые компилируются в сервлеты во время упаковки и к примеру XHTML которые просто обрабатываются и чью структуру держит кэш на сервере. То-есть все те внешние страницы с которыми работает клиент, хотя динамичный контент может исходить из БД или еще откуда-то проходя через business tier(опять-же если есть такой явно выраженный) и попадая на страницы. Если работа с динамичным контентом необходима (в основном это так) то запросы проходят через сервлеты, которые являются классами ответственными за обработку HTTP GET/POST запросов. 


Diagram of Java EE APIs in the web container

 JavaServer Faces
Фреймворк для разработки веб приложений, одно из преимуществ которого является свободное разделение между UI и поведением программы. Он полностью интегрирован со многими ключевыми компонентами Java EE, такими к примеру как EJB (Enterprise Java Beans), JTA (Java Transaction API), JPA (Java Persistence). Содержит API для отражения компонентов и руководства их состоянием. А так-же обеспечивает: управление событиями (), проверку данных, конвертацию данных, определение навигации запросов, поддержку интернационализации, возможность использовать разные faces фреймворки (такие как IceFaces).

JSR299, JSR330
CDI (Contexts and Dependency Injection). Целый спектр возможностей по внедрению зависимостей, причем независимого в поведении и определении компонентов. Придает действительно объектно ориентированный характер взаимоотношению объектов, выводя его на новый уровень за-счет @annotation в сфере  конфигураций, деклараций и квалификаторов, а так-же удобной и полной интеграции с JSF, так как все бины попадают в зону видимости UI компонентов, будь то POJO или EJB 3.1. Акшоном (Action class) может быть все что угодно практически, без лишних деклараций.

ManagedBeans
Легкие бины, по сущности POJO объекты, разработанные как бины JSF, которые обладают доступом к таким сервисам как внедрение зависимостей и interception. В отличие от CDI, они легче но распространяются только в сфере влияния JSF, тогда когда CDI пользуется полной свободы размещения по всему что охватывает собой Java EE.

Bean Validation
Возможность указывать правила проверки JavaBeans задействованных в цикле JSF в виде анотаций.

EJB Lite
Упрощенная спецификация EJB (EJB Lite), которая предусматривает размещение EJB lite в Web Container, без элементов: MDB, EJB2.x, Remote Interface, JAX-WS, JAX-RPC, Timer Service, Asynchronous Session Bean, RMI-IIOP. Тем не менее включает в себя все остальное доступное EJB.

EL
Expression Language, позволяющий отображать значения, вызывать методы и производить другого рода манипуляции Beans. Зачастую используется в UI компонентах (JSP, XHTML), но может и использоваться в самих классах, для обнаружения Beans в контексте (session, request, и.т.д.).

JavaMail
API для email операций.

JSP
Страницы содержащие статический и динамичный контент обрабатываемый сервером. Во время deployment, JSP странницы сервер компилирует в Servlet-ы. Удобство, по крайней мере так было задумано изначально, JPS страниц заключается в том что в отличие о сервлетов существует разделение UI от бизнес логики хоть и не в полной степени, так как в JSP можно писать scriplet-ы (Java код) сопряженные с HTML контентом, некий гибрид но все-же лучше чем просто сервлет с HTML кодом в String-ах.

Connectors (JCA - Java Connector Architecture)
Сеть API для разработки подсоединений к EIS (Entreprise Information System) являющимися источниками информации или поставщиками услуг, к примеру БД или AS/400 mainframe.

Java Persistence (JPA)
Фреймворк отображающий реляционную СУБД в сущностях и на объектно ориентированной основе. Из за несостыковки реляционной и объектно ориентированной моделей, фреймворк предоставляет возможности правильно оценить и реализовать сущности в Java относительно структуры БД, за счет этого сущности приобретают гибкость и простоту проектирования и реализации. JPA помимо стратегий отображения включает в себя инструменты для руководства транзакциями и жизненными циклами сущностей в разных контекстах, а так-же язык JPQL - упрощенный SQL преобразованный на объектно ориентированную основу.

JMS (Java Message Service)
Механизм обеспечивающий работу с месседжами (отправка/получение). Широко используется для разработки независимых, распределенных и асинхронных процессов. Может служить оберточным сервисом для таких систем как IBM MQ.

Web Services
Целый ряд API для разработки Web Services как по стандарту SOAP c WSLD интерфейсом, так и REST (Representational State Transfer), где запрос отправляется в виде в формате GET или POST. Так-же поддерживаются протоколы CORBA и RPC.  

JACC (Java Authorization Contract for Containers)
Контракт определяющий систему авторизации между контейнером (сервером) и самим разработчиком таких систем. По сути дела, это внутренний механизм авторизации сервисов в Java EE.

JASPIC (Java Authentication Service Provider Interface for Containers)
Контракт определяющий систему аутентификации в Java EE. Зачастую, аутентификации разработана индивидуально каждым производителем. В данном случае была выпущена спецификация, правда пока широко не используется так как толком не доработана и выполнена в стиле J2EE 1.4.

JAX-RS
API для разработки RESTful Web Services.

JAX-WS
API для разработки Web Services на основе SOAP и WSDL.

JAX-RPC
API для разработки Web Services через протокол RPC.

SAAJ
API низкого уровня для работы с SOAP Web Services, а так-же позволяет прикреплять приложения к месседжам SOAP.

Business Tier

Здесь сфера деятельности так называемого EJB container-а. Большинство функционала продиктованного требованиями организации под название бизнес логика (business logic) выполняется здесь. Так-же здесь осуществляется соединение с БД. EJB container берет свое название из спецификации о EJB beans которые он способен поддерживать. EJB - это объект оснащенный сетью функций, сервисов предоставляемых контейнером. Такие функции как к примеру поддержка транзакций компонующих процессы, безопасность, потокобезопасность, пулинг (резерв бинов), dependency injection (внедрения зависимых компонентов - DI), контроль над циклом жизни бина и многое другое. В общем EJB обладают мощным потенциалом, достаточным для выполнения сложных операций при этом сохраняя свою простоту и гибкость в разработки и эксплуатации. 

Diagram of Java EE APIs in the EJB container

EJB (Enterprise Java Beans)
Объекты оснащенные рядом сервисов позволяющие быстро удобно и продуктивно разрабатывать и выполнять бизнес решения на сервере. Сервисы включают в себя руководство транзакциями, доступ к ресурсам, CDI (см. выше), пулинг, поддержка параллелизма, реализации Web Services и выполнять роль бинов JSF. Существуют разные типы бинов отображающие жизненный цикл предусмотренный бизнес логикой и отвечающий всем требованием выполнения обеспечивая необходимые ресурсы. Так-же предусмотрены решения разделенного асинхронного процессинга за счет MDB (Message Driven Bean) с использованием JMS (Java Message Service). EJB один из самых ключевых функционалов в Java EE, со многими прочими преимуществами, но это на отдельную тему. 

Sunday 10 August 2014

Weblogic JSF 2 tutorial

Lets create a very simple Web app (WAR) using JSF 2 and drop it on Weblogic.

Prerequisites:

  You would need a weblogic instance installed and have a domain created. If you do not have one, you can download the server from http://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main-097127.html. Then you would need to create a domain, this can be done from Configuration Wizard, where you would choose to create a new domain.

  I am using eclipse for this tutorial, with a simple java project (the reason why i choose not to use the web app project type is that it will give you a better sence of what the application is made of).
My weblogic is instaled in the following directory, this is the directory i will be refering throughout the tutorial:

C:\Oracle\Middleware\Oracle_Home

The directory of the created domain in weblogic i have as:


C:\Oracle\Middleware\Oracle_Home\user_projects\domains\technokon

Install JSF 2 libraries in Weblogic

  First thing we need to do is install the jsf2 library on weblogic (this isn't something you would have to do on JBoss or Glassfish servers for example).
  To do this you need to start-up your weblogic domain, so let's do that and go through the process of installing the library. To start the domain i will launch this file:


startWebLogic.cmd

which is right in the domain directory. You would know that the server is running, when you see something like the following in the cmd window log, the the server is using:

<Aug 7, 2014 8:05:22 PM EDT> <Notice> <WebLogicServer> <BEA-000331> <Started the
 WebLogic Server Administration Server "AdminServer" for domain "technokon" running in development mode.>
<Aug 7, 2014 8:05:22 PM EDT> <Notice> <WebLogicServer> <BEA-000360> <The server started in RUNNING mode.>
<Aug 7, 2014 8:05:22 PM EDT> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to RUNNING.>

Now navigate your browser to:

http://localhost:7001/console

and login to console. Note that i am using the default port 7001, that was configured during the domain creation process.

  Now, on the left menu choose:

Deployments, then click on the  button. Now, navigate to the directory where the jfs-2.0.war is, which i have at:


C:\Oracle\Middleware\Oracle_Home\wlserver\common\deployable-libraries

You will see a file there called:

jsf-2.0.war

  Pick this file and click on the   button. Then on the next page pick Install this deployment as a library.
And click next again on the following 2 pages and  after, this will take you to the configuration page.
Now on this page, set the Restart may be required. Deployment Order: to 99 (default is 100), so it is deployed before other auto-deployable apps. adn click  .

  Now lets move over to the project itself.


Java Project

Start your eclipse and in the workspace create a Java project, I called mine JSFTest.

For this tutorial I am usign Ant to help me, with the following build file that I placed in the root of my java project:

<?xml version="1.0" encoding="UTF-8"?>
<!-- ====================================================================== 
     Aug 7, 2014 3:09:10 PM                                                        

     JSF Test    
     JSF 2 Test application
                   
     iakoupov                                                                
     ====================================================================== -->



<project name="JSF Test" default="build">

 <description>
            JSF 2 Test application
    </description>

 <property name="deploy.dir" value="C:\Oracle\Middleware\Oracle_Home\user_projects\domains\technokon\autodeploy\Test.war" />

 <!-- ================================= 
          target: build              
         ================================= -->
 <target name="build" depends="compile" description="JSF 2 Test application">

  <war destfile="${deploy.dir}" webxml="WebContent\WEB-INF\web.xml">
   <fileset dir="WebContent" includes="*.xhtml" />
   <webinf dir="WebContent\WEB-INF">
   </webinf>
  </war>

 </target>

 <!-- - - - - - - - - - - - - - - - - - 
          target: compile                      
         - - - - - - - - - - - - - - - - - -->
 <path id="jsf2.lib">
  <fileset dir="WebContent\WEB-INF\lib" includes="*.jar" />
 </path>
 <target name="compile">

  <delete dir="WebContent\WEB-INF\classes" />

  <copy todir="WebContent\WEB-INF\classes\resources" overwrite="true">
   <fileset dir="src\resources" includes="**/*.properties" />
  </copy>

  <javac srcdir="src" destdir="WebContent\WEB-INF\classes" includeantruntime="true" classpathref="jsf2.lib" debug="on" />
 </target>

</project>

In that file you would need to change the value of the deploy.dir property so it relates to the location of your domain.

Now lets create other folders in the java project that will compose our web app.

1) Create a folder called WebContent in the root of the project. In there create a folder called WEB-INF.
2) In the WEB-INF folder create 2 folders: classes and lib.
In the lib directory, copy following 2 jar files and add them to the project classpath:


C:\Oracle\Middleware\Oracle_Home\wlserver\modules\javax.enterprise.inject_1.2
C:\Oracle\Middleware\Oracle_Home\wlserver\modules\javax.inject-1.jar


3) Under the src folder, create a package called resources.

3) Now lets copy following files to resources package:  application.properties.

application.properties

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# -- welcome --
welcomeTitle=JSF Blank Application

welcomeHeading=Welcome!

welcomeMessage=This is a JSF blank application. \
 You can find the application.properties file with this message in the src/resources folder.
 
titleStandardNumberConverter = Standard converters for numbers - format numbers
titleStandardDateConverter = Standard converters for date and time
titleCustomCarConverter = Custom car converter
titleCustomDateConverter = Custom date converter


4) To the WEB-INF folder copy the following files: web.xmlweblogic.xml, beans.xml,
faces-config.xml.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>Test</display-name>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>
   <welcome-file>index.xhtml</welcome-file>
  </welcome-file-list> 
  
  
</web-app>

weblogic.xml

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
    <wls:weblogic-version>12.1.3</wls:weblogic-version>
    <wls:context-root>Test</wls:context-root>
</wls:weblogic-web-app>

This file is required by weblogic. In there modules are specified, such as ear, war, ejb-jar files.

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee">
 <scan>
  <exclude name="com.chapter1.*" />
 </scan>
</beans>

Notice the exclude tag, that tells the container not to scan for beans in the pointed-out package.

faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">
 <application>
  <message-bundle>resources.application</message-bundle>
  <locale-config>
   <default-locale>en</default-locale>
  </locale-config>
 </application>

</faces-config>

Notice how compact the file is, since there is no mapping declarations made. This is due to new standard of convenction over configuration (COC) and beans may be declared with annotations as you will see later. This file however still needs to be on the classpath.

5) To the WebContent folder, copy 2 xhtml files that we use for this example: index.xhtmllogin.xhtml.

index.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core">

<f:loadBundle basename="resources.application" var="msg" />

<head>
<title><h:outputText value="#{msg.welcomeTitle}" /></title>
</head>

<body>
 <h3>
  <h:outputText value="#{msg.welcomeHeading}" />
 </h3>
 <p>
  <h:outputText value="#{msg.welcomeMessage}" />
 </p>

 <br />
 <h:link outcome="login" value="Login" />

</body>
</html>


login.xhtml


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core">

<f:loadBundle basename="resources.application" var="msg" />

<head>
<title><h:outputText value="#{msg.welcomeTitle}" /></title>
</head>

<body>
 <f:view>
  <h:form id="loginForm">
   <h:panelGrid columns="2" rendered="#{!login.loggedIn}">
    <h:outputLabel for="username">Username:</h:outputLabel>
    <h:inputText id="username" value="#{credentials.username}" />
    <h:outputLabel for="password">Password:</h:outputLabel>
    <h:inputSecret id="password" value="#{credentials.password}" />

   </h:panelGrid>

   <h:commandButton value="Login" action="#{login.login}"
    rendered="#{!login.loggedIn}" />
   <h:commandButton value="Logout" action="#{login.logout}"
    rendered="#{login.loggedIn}" />

  </h:form>
 </f:view>
</body>
</html>

6) Create a package under src folder in eclipse and create Login, User and Credentials classes in there.

Login.java

 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
package com.technokon.bean;

import java.io.Serializable;

import javax.enterprise.inject.Model;
import javax.enterprise.inject.Produces;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;

@SessionScoped
@Model
public class Login implements Serializable {
 private static final long serialVersionUID = -7665912439280494601L;
 
 @Inject
 private Credentials credentials;
 
 private User user;
 
 public void login() {
  // DB
  if (credentials.getUsername().equalsIgnoreCase("ADMIN")
    && credentials.getPassword().equals("password")) {
   user = new User();
   user.setUsername(credentials.getUsername());
   user.setPassword(credentials.getPassword());
  }
 }
 
 public void logout() {
  user = null;
 }
 
 public boolean isLoggedIn () {
  return user != null;
 }
 
 @Produces
 User getCurrentUser() throws Exception {
  if (user == null) {
   throw new Exception("Not logged in");
  } else {
   return user;
  }
 }

}

User.java

 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
package com.technokon.bean;

import javax.enterprise.inject.Model;

@Model
public class User {
 
 private String username;
 
 private String password;
 
 private String firstName;
 
 private String lastName;

 public String getUsername() {
  return username;
 }

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

 public String getPassword() {
  return password;
 }

 public void setPassword(String password) {
  this.password = password;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }
 
 

}

Credentials.java

 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
package com.technokon.bean;

import javax.enterprise.inject.Model;

@Model
public class Credentials {
 
 private String username;
 
 private String password;

 public String getUsername() {
  return username;
 }

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

 public String getPassword() {
  return password;
 }

 public void setPassword(String password) {
  this.password = password;
 }
 
 
}