Pokazywanie postów oznaczonych etykietą hibernate. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą hibernate. Pokaż wszystkie posty

sobota, 24 stycznia 2009

Hibernate Validator + DataSource

Witam, dziś będzie o dostępie do dany z bazy, w hibernate validatorach. Przed przeczytaniem polecam zajrzeć na jeden z poprzednich postów, link. Pomysł, aby tym się zająć zrodził się podczas tworzenia formularza rejestracyjnego w moim projekcie. Uznałem, że fajnie byłoby, gdyby automatycznie po wpisaniu jakiegoś loginu, validator sprawdzał czy takowy istnieje już w naszej bazie i informował nas o tym.
Musimy zacząć od zmodyfikowania pliku persistance.xml, dodamy nowe property, dzięki któremy będziemy mogli pobrać obiekt typu EntityManagerFactory z pomocą JNDI. Ten zaś z kolei da nam dostęp do EntityManagera. Tak więc dodajemy wpis:

...
<properties>
...
<property name="jboss.entity.manager.factory.jndi.name" value="java:/myEntityManagerFactory"/>
</properties>
</persistence-unit>

Tworzymy teraz nowy validator:

@Documented
@Target(FIELD)
@Retention(RUNTIME)
@ValidatorClass(UsernameValidator.class)
public @interface Username {
String message() default "Podany login juz istnieje";
}

oraz

public class UsernameValidator implements Validator<Username>, Serializable
{
private static final long serialVersionUID = 1L;
EntityManager entityManager;

public void initialize(Username parameters)
{
}

public boolean isValid(Object value)
{
Context ctx = null;
String login = (String) value;
try
{
ctx = new InitialContext();
} catch (NamingException e)
{
e.printStackTrace();
}
EntityManagerFactory entityManagerFactory = null;
try
{
entityManagerFactory = (EntityManagerFactory) ctx.lookup("java:/myEntityManagerFactory");
} catch (NamingException e)
{
e.printStackTrace();
}
entityManager = entityManagerFactory.createEntityManager();

Query q = entityManager.createQuery("FROM Osoba WHERE login = '" + login + "'");
try
{
q.getSingleResult();
return false;
} catch (final NoResultException e)
{
return true;
}
}
}

Jak widzimy używając JNDI pobieramy EntityManagerFactory. Z pomocą entityManagera tworzymy zapytanie, a w bloku try catch, próbujemy uzyskać wynik tego zapytania, jeżeli metoda wyrzuci wyjątek znaczy to, że podany login nie istnieje w bazie. Zakładam, że loginy przechoowywane sa w tabeli Osoba w kolumnie login. Aby skorzystać z naszego validatora wystarczy nad odpowiednim polem dać adnotacje @Username.

poniedziałek, 19 stycznia 2009

Co nieco o Hibernate Validator

Witam, dziś parę słów na temat walidacji, a dokładniej walidacji przy użyciu Hibernate Validator. Walidacja jest niezwykle przydatną funkcją podczas tworzenia wszelkiego rodzaju formularzy, możemy kontrolować to, co użytkownik może wprowadzić. Jeśli chodzi o walidatory JSF to dobry tutorial znajduje się tutaj. My jednak będziemy zajmować się narzędzie od Hibernate'a. Stronę projektu znajdziecie tutaj, zaś tutaj dokumentacje. Jeśli chodzi o jakieś dodatkowe JARy to w JBossie nie martwimy się o nie, zaś w Geronimo możliwe, że trzeba je będzie ściągnąć ze stronki Hibernate. W poprzednim poście napisałem nieco o RichFaces, więc teraz użyjemy go tworząc bardzo prosty formularz.

Jeśli chodzi o plik web.xml to nie zmienił się on od pooprzeniego razu.

Przejdźmy do zdefiniowania mbeana:

package com.blogspot.javazpiwnicy.mbeans;

import java.util.Date;

import org.hibernate.validator.Email;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.Past;
import org.hibernate.validator.Pattern;

import com.blogspot.javazpiwnicy.validator.Urodziny;

public class Osoba {
@NotEmpty(message = "Pole nie moze byc puste")
@Length(min = 2, max=15, message = "Minimalna dlugosc to 2, maksymalna 15")
private String login;

@NotEmpty(message = "Pole nie moze byc puste")
@Email(message = "To nie jest adres email")
private String email;

@Pattern(regex = "[0-9]{2}( |-)?[0-9]{3}", message = "Niepoprawny kod pocztowy")
private String kodPocztowy;

@Past(message = "Data nie jest z przeszlosci")
@Urodziny
private Date urodziny;

public String getLogin() {
return login;
}

public void setLogin(String login) {
this.login = login;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getKodPocztowy() {
return kodPocztowy;
}

public void setKodPocztowy(String kodPocztowy) {
this.kodPocztowy = kodPocztowy;
}

public Date getUrodziny() {
return urodziny;
}

public void setUrodziny(Date urodziny) {
this.urodziny = urodziny;
}

public String dodaj() {
return "success";
}
}

Widzimy tutaj nad poszczególnymi polami Osoby różne adnotacje. Ich opis można znaleźć w dokumentacji. Do wyświetlania informacji służy "message", bez tego użyte zostaną standardowe informacje o błędzie. Oczywiście można te informacje pobierać z plików properties wystarczy wpisać "message={naszKluczWPliku}". Adnotacja Urodziny to nasz własny walidator sprawdzający czy osoba ma 18 lat.
Przejdźmy teraz do stworzenia własnego walidatora. Najpierw tworzymy deskryptor(adnotacja):

package com.blogspot.javazpiwnicy.validator;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import org.hibernate.validator.ValidatorClass;

@Documented
@Target(FIELD)
@Retention(RUNTIME)
@ValidatorClass(UrodzinyValidator.class)
public @interface Urodziny {
String message() default "Nie masz 18 lat";
}

A następnie plik walidatora:

package com.blogspot.javazpiwnicy.validator;

import java.util.Calendar;
import java.util.Date;
import org.hibernate.validator.Validator;

public class UrodzinyValidator implements Validator<Urodziny>{

public void initialize(Urodziny parameters) {
}

public boolean isValid(Object value){
Calendar dataUrodzin = Calendar.getInstance();
dataUrodzin.setTime((Date)value);
Calendar kiedys = Calendar.getInstance();
kiedys.add(Calendar.YEAR, -18);

if(dataUrodzin.before(new GregorianCalendar(kiedys.get(Calendar.YEAR),
kiedys.get(Calendar.MONTH), kiedys.get(Calendar.DAY_OF_MONTH))))
return true;
return false;
}
}
Dziękuje przy okazji Szymonowi za wskazówkę dotyczącą Calendar'a.
Tak więc zostaje nam jeszcze napisanie formularza:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>javazpiwnicy.blogspot.com</title>
</head>
<body>
<f:view>
<center><rich:panel header="Formularzyk" style="width: 400px">
<a4j:form>
<h:panelGrid columns="3">
<h:outputText value="Login" />
<h:inputText id="login" value="#{osoba.login}">
<rich:ajaxValidator event="onblur" />
</h:inputText>
<rich:message for="login"/>

<h:outputText value="Email" />
<h:inputText id="poczta" value="#{osoba.email}">
<rich:ajaxValidator event="onblur" />
</h:inputText>
<rich:message for="poczta"/>

<h:outputText value="Kod pocztowy" />
<h:inputText id="kod" value="#{osoba.kodPocztowy}">
<rich:ajaxValidator event="onblur" />
</h:inputText>
<rich:message for="kod"/>

<h:outputText value="Data urodzin" />
<rich:calendar id="dataUrodzenia" value="#{osoba.urodziny}">
<rich:ajaxValidator event="onclick" />
</rich:calendar>
<rich:message for="dataUrodzenia" />

<h:outputText value="" />
<a4j:commandButton value="Dodaj" action="#{osoba.dodaj}" />
</h:panelGrid>
</a4j:form>
</rich:panel></center>
</f:view>
</body>
</html>

I to byłoby na tyle. Po wpisaniu błędnych danych w formularzu powinna pojawić się stosowna informacja.

wtorek, 30 grudnia 2008

JBoss 5.0 i DataSource

Witam
Integracja JBoss-a z Eclipsem już za nami jednak by spokojnie pisać aplikacje Java EE pozostało kilka rzeczy do zrobienia. Najpierw zdefiniujemy JBoss-owi DataSource, czyli naszą bazę danych. Ja zdecydowałem się na PostgreSQL, Bartek na MySQL.
Wchodzimy najpierw do folderu z JBoss-em (dalej nazywany jboss_home) następnie docs\examples\jca i kopiujemy stąd przykładowy plik konfguracyjny naszej bazy. W moim przypadku postgres-ds.xml, dla tych co wybrali MySQL mysql-ds.xml. Plik ten wklejamy do jboss_home\server\default\deploy\. Zajrzyjmy do środka. Dla postgresa powinien wyglądać mniej więcej tak:
<datasources>
  <local-tx-datasource>
    <jndi-name>PostgresDS</jndi-name>
    <connection-url>jdbc:postgresql://[servername]:[port]/[databasename]</connection-url>
    <driver-class>org.postgresql.Driver</driver-class>
    <user-name>x</user-name>
    <password>y</password>
    <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
    <metadata>
      <type-mapping>PostgreSQL 7.2</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>
Po kolei co jest co :
  • jndi-name jest to nazwa pod jaką zostanie zarejestrowana w JBoss-ie nasza baza.

  • connection-url jest to powiedzmy link do naszej bazy. Zamiast [servername] wpisujemy 127.0.0.1 ew localhost (lub adres serwera, na którym mamy serwer bazy), zamiast [port] wpisujemy port, na którym nasłuchuje nasza baza (dla postrgresa defaultowo 5432), [database] nazwa naszej bazy danych. U mnie wygląda to tak: jdbc:postgresql://127.0.0.1:5432/pz2 .

  • driver class mówi JBoss-owi jakiego rodzaju sterowników (o tym za chwile) ma szukać.

  • user-name i password już tłumaczyć chyba nie trzeba.

Sterowniki. Dla PostgreSQL dostępne pod http://jdbc.postgresql.org/download.html. Dla Javy 1.6 wybieramy wersje sterownika JDBC4, a dla pozostałych (obecnie serwery aplikacji obsługują do 1.5 więc wersja dla nas) JDBC3.
Dla MySQL http://dev.mysql.com/downloads/connector/j/5.1.html wybieramy *.tar.gz lub *.zip. Pobrane pliki *.jar (w wypadku MySQL należy wypakować i z głównego folderu skopiować connector) wrzucamy do jboss_home\server\default\lib\

Uff po tym wszystkim tworzymy projekt EAR tak jak zwykliśmy to robić, z warstwą biznesową i webową. Zostały nam do wykonania jeszcze dwie rzeczy.
W EarContent\META-INF\ tworzymy plik jboss-api.xml i wpisujemy:

<jboss-app>
  <loader-repository>
    MojProjekt:archive=ProjektEAR.ear
  </loader-repository>
</jboss-app>

Gdzie: MojProjekt jest to napis który w pewien sposób identyfikuje nasz projekt w JBossie (tych, którzy chcą się dowiedzieć więcej odsyłam do dokumentacji JBoss-a, a ProjektEAR.ear jest to nazwa dla zbudowanego projektu ProjektEAR przez eclipse-a (np. projekt EAR o nazwie asd po zbudowaniu da plik asd.ear).
Potem w części EJB musimy wyedytować plik persistence.xml (standardowo w ejbModule\META-INF\ ) u mnie wygląda tak.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="ProjektEJB">
  <provider>org.hibernate.ejb.HibernatePersistence</provider>
  <jta-data-source>java:/PostgresDS</jta-data-source>
  <properties>
    <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
    <property name="hibernate.hbm2ddl.auto" value="update"/>
  </properties>
</persistence-unit>
</persistence>
Z tego wszystkiego interesuje nas:

  • name="ProjektEJB" nazwa części biznesowej projektu (akurat moja to ProjektEJB)

  • jta-data-source nazwa jndi naszej bazy danych skąd to wziąść? Nazwę podaliśmy w pliku postgres-ds.xml lub mysql-ds.xml (w pliku może być zdefiniowana więcej niż jedna baza!).
    Przedrostek java:/ jest związany z jndi, które mnie odrzucało od poprzednich wersji JBossa więc pominę co to, a powiem, że musi tu być i kropka.

  • hibernate.dialect mówi Hibernate-owi jakim "dialektem" SQL-a ma się posługiwać w komunikacji z bazą danych. Dla PostgreSQL jest to org.hibernate.dialect.PostgreSQLDialect dla MySQL5.0 org.hibernate.dialect.MySQL5Dialect (pełna lista tu).

  • hibernate.hbm2ddl.auto w jaki sposób hibernate "zachowuje się" w naszej bazie. Przy ustawieniu create-drop w momencie rozruchu tworzy tabele, ale gdy SessionFactory kończy swój żywot (czyli jak wyłączymy naszą aplikacje) sprząta po sobie w bazie. Jeśli chcemy zachować swoje dane musimy ustawić create lub update. Idąc za materiałem znalezionym w internecie użyłem update.

Reszta pozostaje bez zmian (pełną liste properties można znaleźć na tej stronie). W tym momencie możemy już pisać encje, beany mając dostęp do wstrzyknięć zależności i wszystkiego co Java EE nam zapewnia.
A tutaj macie prosty projekt działający pod JBossem i bazą PosrtgreSQL. Jako, że to projekt z Eclipse może być konieczne ponowne ustawienie zależności. Czyli:



A następnie:



W razie problemów pisać w komentarzach co się dzieje.
Życzę milej zabawy.

Drzazga:
W celu przeglądania wyników naszej pracy na bazie danych możemy posłużyć się phpMyAdmin albo zestawem programów prosto od Suna MySql Tools. Konfiguracja i przeglądanie zawartości bazy jest dosyć proste, więc nie będę się rozpisywał.
Jeśli wybraliście Postgresa to wraz z nim instaluje się pgAdmin III, w którym będziecie zarządzać bazą. HF