четверг, 28 ноября 2013 г.

Внедрение методов Spring

Прием внедрения методов  позволяет внедрять в компоненты определения целых методов.
Spring предоставляет Java-программистам возможность внедрения методов в Java-классы во время выполнения.

Фреймворк Spring поддерживает две формы внедрения методов:
  •  ‰ замещение  метода    – позволяет во время выполнения заместить существующий метод (абстрактный или конкретный) новой реализацией;
  •  ‰ внедрение метода чтения    – позволяет во время выполнения  заместить существующий метод (абстрактный или конкретный) новой реализацией, возвращающей определенный компонент из контекста Spring.
Пример замещения методов


<bean id="magicBox" class="com.springinaction.springidol.MagicBoxImpl">
      <replaced-method  name="getContents"  replacer="tigerReplacer" />
</bean>
<bean id="tigerReplacer" class="com.springinaction.springidol.TigerReplacer" />

Сейчас в компоненте  magicBox имеется элемент  <replaced-method> . Как следует из названия, этот элемент используется для замены метода новой реализацией. В данном случае атрибут name указывает имя замещаемого метода  getContents().

package com.springinaction.springidol;
import java.lang.reflect.Method;
import org.springframework.beans.factory.support.MethodReplacer; 
public class TigerReplacer implements MethodReplacer {
 public Object reimplement(Object target, Method method, // Подмена
          Object[] args) throws Throwable {             // метода
        return "A ferocious tiger"; // Помещает тигра в ящик
    }
}

Класс TigerReplacer реализует интерфейс  MethodReplacer, требующий реализации единственного метода  reimplement(). Этот метод принимает три аргумента: объект, в котором будет производиться замещение метода, метод, подлежащий замещению, и массив аргументов, принимаемых методом.
Тело метода  reimplement() фактически становится новой реализацией метода  getContents().

Способ применения:
Прием внедрения метода с успехом может использоваться, когда фактическая реализация замещаемого метода не известна до момента развертывания. К этому моменту класс с замещающей реализацией метода можно оформить в виде JAR-файла и поместить его в библиотеку классов (classpath) приложения. 

Пример внедрения метода чтения

Внедрение    через метод чтения – это особый случай внедрения методов, когда объявляется метод (обычно абстрактный), возвращающий компонент определенного типа, но фактически возвращаемый компонент определяется в контексте Spring.

package com.springinaction.springidol;
public abstract class Instrumentalist implements Performer {
    public Instrumentalist() {}
    public void perform() throws PerformanceException {
        System.out.print("Playing " + song + " : ");
        getInstrument().play();   // Используется внедряемый метод
    }                        // getInstrument()
    private String song;
    public void setSong(String song) {
        this.song = song;
    }
    public abstract Instrument getInstrument(); // Внедряемый метод

}

Для поддержки внедрения методов чтения фреймворк Spring предлагает элемент  <lookup-method> . Как и  <replaced-method>, элемент <lookup-method> замещает существующий метод новой реализацией во время выполнения. 

<bean id="stevie" class="com.springinaction.springidol.Instrumentalist">
  <lookup-method name="getInstrument" bean="guitar" />
  <property name="song" value="Greensleeves" />
</bean>

Как и в элементе  <replaced-method>, атрибут  name элемента  <lookup-method> определяет замещаемый метод. Здесь замещается метод getInstrument(). Атрибут  bean определяет компонент, возвращаемый методом getInstrument().

Важно помнить, что при использовании элемента  <lookup-method> для внедрения метода чтения совсем необязательно, чтобы замещаемый метод был методом чтения (то есть методом, имя которого начинается со слова  get). С помощью элемента  <lookup-method> можно заместить любой метод, возвращающий некоторое значение.

Следует также отметить, что даже при том, что прием внедрения методов позволяет замещать их реализации, нет никакой возможности изменить сигнатуру метода. Типы параметров и возвращаемого значения должны оставаться такими, какие они есть. 

понедельник, 25 ноября 2013 г.

Оператор Элвиса или интересности Spring

При использовании трехместного оператора в SpEL выражении возможно использование одного и того же выражения. Например

<property name="song" value="#{kenny.song != null ? kenny.song : 'Greensleeves'}"/> 

Это выражение построено правильно, но в нем имеется повторяющийся элемент – ссылка на свойство kenny.song. Язык SpEL предлагает разновидность трехместного оператора, упрощающую подобные выражения:

<property name="song" value="#{kenny.song ?: 'Greensleeves'}"/>

Как и в предыдущем примере, выражение вернет значение свойства kenny.song или «Greensleeves», если свойство kenny.song равно null. При таком способе использования оператор ?: называют оператором Элвиса. Этим странным названием оператор обязан сравнению со смайликами – если повернуть его на 90 градусов (по часовой стрелке), вопросительный знак будет напоминать прическу знаменитого Элвиса Пресли (Elvis Presley).

Внедрение коллекций в компоненты Spring

А возможно ли с помощью Spring инициализировать свойства, имеющие множество значений, что, если свойство является коллекцией значений? 
Фреймворк Spring предлагает четыре типа элементов определения коллекций, которые пригодятся для конфигурирования значений, являющихся коллекциями.


Элементы  <list>   и  <set>   можно использовать для настройки свойств, которые являются массивами или одной из реализаций java.util.Collection. 
Что касается элементов  <map>   и  <props>  , они соответствуют коллекциям с интерфейсами java.util.Map   и java.util.Properties   соответственно. Эти типы коллекций можно использовать, когда требуется коллекция, состоящая из пар ключ/значение. 

Пример 1 (<list>)
<bean id="hank"
     class="com.springinaction.springidol.OneManBand">
  <property name="instruments">
    <list>
      <ref bean="guitar" />
      <ref bean="cymbal" />
      <ref bean="harmonica" />
    </list>
  </property>
</bean>

Пример 2(<map>)
<bean id="hank" class="com.springinaction.springidol.OneManBand">
  <property name="instruments">
    <map>
      <entry key="GUITAR" value-ref="guitar" />
      <entry key="CYMBAL" value-ref="cymbal" />
      <entry key="HARMONICA" value-ref="harmonica" />
    </map>
  </property>
</bean>

Пример 3(<props>)
<bean id="hank" class="com.springinaction.springidol.OneManBand">
  <property name="instruments">
    <props>
      <prop key="GUITAR">STRUM STRUM STRUM</prop>
      <prop key="CYMBAL">CRASH CRASH CRASH</prop>
      <prop key="HARMONICA">HUM HUM HUM</prop>
    </props>
  </property>
</bean>


Область действия Spring-компонента

По умолчанию все компоненты Spring единичны. Когда контейнер передает компонент (либо через связывание, либо как результат вызова метода контейнера  getBean()  ), всегда будет передан тот же самый экземпляр компонента.
При объявлении  <bean> компонента можно определить область его действия. 

Области действия:
singleton - В каждом контейнере Spring может быть создан только один компонент (по умолчанию)
prototype - Позволяет создавать произвольное количество компонентов (по одному на каждое обращение)
Дополнительные области для Spring-MVC приложений:
request - Область действия компонента ограничивается HTTP-запросом. Может применяться только в веб-приложениях Spring (например, использующих Spring MVC)
session - Область действия компонента ограничивается HTTP-сеансом. Может применяться только в веб-приложениях Spring (например, использующих Spring MVC)
global-session - Область действия компонента ограничивается глобальным HTTP-сеансом. Может применяться только в портлетах

Понятие единичных компонентов ограничено областью действия контекста Spring. В отличие от истинных классов-одиночек, гарантирующих существование единственного экземпляра на каждый загрузчик классов (classloader), для единичных компонентов в Spring гарантируется 
только наличие единственного экземпляра компонента в контексте приложения – ничто не мешает создать экземпляр того же класса традиционным способом или даже создать несколько объявлений <bean> для одного и того же класса.

среда, 20 ноября 2013 г.

Жизненный цикл компонента Spring

1.  Spring создает экземпляр компонента.
2.  Spring внедряет значения и ссылки на компоненты в свойства данного компонента.
3.  Если компонент реализует интерфейс  BeanNameAware, Spring передает идентификатор компонента методу  setBeanName()  .
4.  Если компонент реализует интерфейс  BeanFactoryAware, Spring вызывает метод setBeanFactory()  , передавая ему саму фабрику компонентов.
5.  Если компонент реализует интерфейс  ApplicationContextAware, Spring вызывает метод  setApplicationContext(), передавая ему ссылку на вмещающий контекст приложения.
6.  Если какие-либо из компонентов реализуют интерфейс  BeanPost Processor, Spring вызывает их методы  postProcessBeforeInitialization().
7. Если какие-либо из компонентов реализуют интерфейс InitializingBean, Spring вызывает их методы afterPropertiesSet(). Аналогично, если компонент был объявлен с атрибутом  init-method, вызывается указанный метод инициализации.
8. Если какие-либо из компонентов реализуют интерфейс BeanPostProcessor, Spring вызывает их методы  postProcessAfterInitialization().
9.  В этот момент компонент готов к использованию приложением и будет сохраняться в контексте приложения, пока он не будет уничтожен.
10. Если какие-либо из компонентов реализуют интерфейс DisposableBean, Spring вызывает их методы  destroy()  . Аналогично, если компонент был объявлен с атрибутом  destroy-method, 
вызывается указанный метод.

Про Spring

Тут будут некоторые заметки про Spring. Чтобы, когда потребуется, легко освежать у себя в голове.

Два кита, на которых зиждется Spring это Spring DI и Spring AOP.

По поводу Spring DI можно отметить следующий момент. Благодаря DI объекты получают свои зависимости во время создания от некоторой третьей стороны, координирующей работу каждого объекта в системе. Объекты не создают и не получают свои зависимости самостоятельно – зависимости внедряются в объекты.

Основное преимущество DI – слабая связанность. Если объект взаимодействует со своими зависимостями только через их интерфейсы (ничего не зная о конкретных реализациях или особенностях их создания), зависимости можно будет замещать любыми другими реализациями, без необходимости учитывать эти различия в самом объекте.

Однако для того, чтобы определять какой именно объект был внедрен используется связывание.
Связывание - это процесс создания связей между прикладными компонентами.

Фреймворк Spring поддерживает множество способов связывания компонентов, но наиболее общим из них является способ на основе XML.

В приложении, созданном на основе Spring, контекст приложения загружает определения компонентов и связывает их вместе. За создание объектов, составляющих приложение, и их связывание полностью отвечает контекст приложения.

Аспектно-ориентированное программирование   позволяет оформлять функциональность, используемую в приложении, в виде многократно используемых компонентов.

Системные службы, такие как журналирование, управление транзакциями и безопасность, часто находят свое отражение в компонентах, основная задача которых заключается в чем-то другом. Такие системные службы обычно называют сквозными задачами, потому что в их работу может вовлекаться несколько компонентов  системы.
AOP делает возможным отделение этих служб и декларативное их применение к необходимым компонентам.

Прежде чем использовать волшебство Spring по превращению объекта в аспект, его сначала необходимо объявить компонентом Spring с помощью элемента <bean>. Дело в том, что с аспектами Spring можно выполнять любые операции, которые можно выполнять с другими компонентами Spring, такие как внедрение их в виде зависимостей.

Фреймворк Spring стремится помочь в устранении шаблонного кода путем заключения его в шаблоны. Класс JdbcTemplate из фреймворка Spring позволяет выполнять операции с базой данных без лишних церемоний, требуемых традиционным JDBC.

Фреймворк Spring имеет не один контейнер. В его состав входят несколько реализаций контейнера, которые подразделяются на два разных типа.  Фабрики компонентов  (bean factories) (определяются интерфейсом  org.springframework.beans.factory.BeanFactory ) – самые простые из контейнеров, обеспечивающие базовую поддержку DI.  Контекст приложений  (application contexts) (определяется интерфейсом  org.springframework.context.ApplicationContext ) основан на понятии фабрик компонентов и реализует прикладные службы фреймворка, такие как возможность приема текстовых сообщений из файлов свойств и возможность подписывать другие программные компоненты на события, возникающие в приложении.

пятница, 8 ноября 2013 г.

MyBatis области видимости базовых понятий (SqlSessionFactoryBuilder, SqlSessionFactory и т.п.)

SqlSessionFactoryBuilder 
Должен создаваться единожды за все время работы приложения и только для того, чтобы создать SqlSessionFactory. Поэтому область использования данного объекта  - метод. Категорически не рекомендуется использовать  SqlSessionFactoryBuilder  для создания множества SqlSessionFactory.

SqlSessionFactory 
Создается 1 экземпляр на все приложение и используется на протяжении всего времени выполнения приложения. Лучше всего использовать область видимости - приложение. Самый простой способ использовать паттерн Singleton. Или же использовать механизм Dependency Injection, для создания объекта singleton за счет контейнера Spring.

SqlSession 
Каждый поток должен иметь свой экземпляр, поэтому область использования должна быть - метод. Экземпляр  SqlSession нельзя использовать совместно и он не является потокобезопасным. Ни за что в жизни нельзя хранить ссылку на него в статической переменной или переменной класса.
Очень важно всегда закрывать сессию после использования.

SqlSession session = sqlSessionFactory.openSession(); 
try { 
  // do work 
} finally { 
  session.close(); 


Mapper Instances 
Область использования должна быть такая же как и у SqlSession, то есть область использования д.б. - метод.


Введение в MyBatis

MyBatis - это ORM-фреймворк для работы с базой данных, он позволяет работать с простым SQL, хранимыми процедурами.

Для конфигурации MyBatis может использовать XML или аннотации.

Каждое приложение с использованием MyBatis сосредоточено вокруг экземпляра SqlSessionFactory. Экземпляр этого класса можно получить, используя SqlSessionFactoryBuilder, используя либо конфигурационный класс XML, либо же пользовательский класс с параметрами конфигурации.

Простой пример Configuration.xml 
<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE configuration 
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration> 
  <environments default="development"> 
      <environment id="development"> 
      <transactionManager type="JDBC"/> 
      <dataSource type="POOLED"> 
        <property name="driver" value="${driver}"/> 
        <property name="url" value="${url}"/> 
        <property name="username" value="${username}"/> 
        <property name="password" value="${password}"/> 
      </dataSource> 
    </environment> 
  </environments> 
  <mappers> 
    <mapper resource="org/mybatis/example/BlogMapper.xml"/> 
  </mappers> 

</configuration>

В секции mappers указываются пути к файлам, в которых содержится маппинг сущностей на таблицы БД.

Чтобы напрямую обращаться к базе данных (выполнять различные запросы) от SqlSessionFactory надо получить экземпляр SqlSession

SqlSession session = sqlSessionFactory.openSession(); 
try { 
  BlogMapper mapper = session.getMapper(BlogMapper.class); 
  Blog blog = mapper.selectBlog(101); 
} finally { 
  session.close(); 



Где BlogMapper это интерфейс, в котором описаны все методы, для работы с БД.

Вот фрагмент простого тестового класса, который получает доступ к SqlSession и работает с бд

public static void main(String[] args){

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
Reader reader;
try {
reader = Resources.getResourceAsReader("Configuration.xml");
SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(reader);
SqlSession sqlSession = sessionFactory.openSession();
try{
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
long id  = 1L;
User user = userMapper.findById(id);
} finally {
sqlSession.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

среда, 6 ноября 2013 г.

Apache UIMA, понять и разобраться

Analysis Engine (AE) - программа, которая анализирует артефакты (документы).

AE состоит из строительных блоков, называемых аннотаторами.

Аннотатор (Annotator) - компонент, который содержит анализирующую логику.

Если AE содержит 1 аннотатор - Primitive AE
Если АЕ содержит несколько аннотаторов  - Aggregate AE

Артефакт - это неструктурированная вещь, которая может анализироваться аннотатором, например текстовый документ, видео, изображение.

Аннотаторы на выходе дают  результат в виде типизированных структур свойств (Feature Structures). Feature Structures - это структуры данных, имеющие тип и множество пар (атрибут, значение).

Аннотация (Feature Name || TypeName) - это определенный тип Feature Structures, который присоединяется к части анализируемого документа (выходной тип данных).

Т.е. Feature Structures это совокупность всех аннотаций, которые применит анализатор или совокупность типов выходных данных.

Common Analysis Structure (CAS) - это все структуры свойств, включая аннотации.

Необходимо выполнить несколько действий, чтобы написать и протестировать простой UIMA аннотатор:
  1. Определить CAS типы, которые аннотатор будет использовать.
  2. Сгенерировать Java-классы для этих типов.
  3. Написать код аннотатора.
  4. Создать AE - дескриптор.
  5. Протестировать аннотатор.
Немного о типах данных в UIMA
UIMA определяет примитивные типы данных такие как Boolean, Byte, Short, Integer, Long, Float, and Double, а также массивы примитивных типов. В иерархии системы типов в UIMA самым главным является TOP (как аналог Object в java). А также есть FSArray это массив Feature Structures и Annotation.

Во встроенном типе Annotation 3 свойства (Feature): 
  1. begin - смещение в тексте относительно начала аннотации
  2. end - смещение в тексте относительно конца аннотации
  3. sofa - это содержимое документа между begin и end
Написание аннотатора
Все аннотаторы должны реализовать три метода интерфейса AnalysisComponent:
  1. initialize - вызывается фреймворком единожды, когда создается экземпляр аннотатора
  2. process - вызывается на каждый обрабатываемый элемент
  3. destroy - вызывается, после того как работа с аннотатором завершена
Apache UIMA гарантирует, что на потокобезопасность при вызове аннотатора, а именно,  один экземпляр аннотатора на один поток. 

вторник, 5 ноября 2013 г.

Eclipse Maven Dynamic Web Project

Первый линк, который бросается на комбинацию этого поискового запроса

http://stackoverflow.com/questions/10888068/java-dynamic-web-project-with-maven-and-eclipse

Резюме: если вы создаете dynamic web project, то конечным продуктом д.б. WAR или EAR. WAR или EAR это JAR файлы со специфической структурой, который могут быть задеплоены сервером приложений или контейнером сервлетов.

Самый легкий способ настроить Maven для web-проектов, это использовать архетип:
mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp
Если мы создаем проект с данным архетипом, то в этом случае генерируется простая
структура проекта и pom.xml

Вот так выглядит содержимое WAR-архива


Натыкаемся на интересную запись: you should not use the mvn eclipse:eclipse command to create the Eclipse project. This plugin can only generate WTP(Web Tools Platform) projects for very old Eclipse versions (WTP 2.0 is the maximum).

После того как у нас есть pom.xml рекомендуется определить версию java:
Это неплохая идея привязать проект к определенной версии JDK, это гарантирует, то что приложение всегда будет строиться с указанной версией JDK, несмотря на обновления

<build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
    </plugins>
    <finalName>myprojectname</finalName>
  </build>

Теперь, чтобы импортировать maven проект в eclipse и в целом получить необходимый функционал maven в eclipse, следует поставить плагин m2eclipse.

После чего File->Import->Existing Maven Project, указываем путь к папке проекта, где лежит pom.xml и готово.


Бесконечная ходьба по граблям заканчивается

Добрый вечер. Так как я привыкла ходить по граблям, то я решила написать свой блог именно об этом, чтобы потом можно было найти выход из определенной ситуации, а не снова просматривать кучу форумов в поисках решений