www.devcastzone.com
1
Z
AAWANSOWANE WYKORZYSTANIE BIBLIOTEKI
EXT
GWT
W APLIKACJACH OPARTYCH O
G
OOGLE
W
EB
T
OOLKIT
Moduł 5: Komunikacja aplikacji z serwerem
Ćwiczenie 1: Callback
Treść:
Stworzyd funkcję zwrotną, która będzie reagowała na zwrot listy łaocuchów tekstowych.
Jeżeli lista zostanie zwrócona to należy każdy jej element wyświetlid w konsoli. Jeżeli lista nie
została poprawnie zwrócona należy wydelegowad go do nowo rzucanego wyjątku klasy
RunntimeException.
Instrukcja rozwiązania:
1. Stworzyd funkcję zwrotną klasy asyncCallback wraz z typem generycznym
określającym listę ciągów tekstowych.
2. Zaimplementowad metodę onFailure, która rzuca nowy wyjątek klasy
RuntimeException, i przekazuje wyjątek z funkcji zwrotnej
3. Zaimplementowad metodę onSuccess, w której należy przeiterowad zwraaną listę a
następnie każdy element wyświetlid na ekranie.
Rozwiązanie:
Ćwiczenie 2: Asynchronous interface
Treść:
Stworzyd interfejs asynchroniczny do serwisu posiadającego następujące metody:
interface
UserService {
AsyncCallback<List<String>> callback =
new
AsyncCallback<List<String>>() {
@Override
public
void
onFailure(Throwable caught) {
throw
new
RuntimeException(caught);
}
@Override
public
void
onSuccess(List<String> result) {
for
(String row : result) {
System.out.println(
"Row: "
+ row);
}
}
};
www.devcastzone.com
2
public
void
updateUserName(Long id, String userName);
public
String getUserName(Long id);
public
List getUserNamesListByFilter(String filter);
}
Instrukcja rozwiązania:
1. Należy zdefiniowad nowy interfejs o nazwie UserListAsync
2. Należy dodad deklarację nowej metody updateUserName, która nic nie zwraca, z
przyjmowanymi parametrami: identyfikator, funkcja zwrotna , nic nie zwracająca
3. Należy dodad deklarację nowej metody getUserName, która nic nie zwraca, z
przyjmowanymi parametrami: identyfikator, funkcja zwrotna zwracająca tekstowy
typ danych
4. Należy dodad deklarację nowej metody getUserNameListByFilter, która nic nie
zwraca, z przyjmowanymi parametrami: tekstowy filtr, funkcja zwrotna , zwracająca
listę typów tekstowych
Rozwiązanie:
Ćwiczenie 3: GWT-RPC
Treść:
Stworzyd interfejs synchroniczny, asynchroniczy oraz implementację do komunikacji za
pomocą GWT-RPC. Potencjalne wywołanie metody getFeedList serwisu powinno zwrócid
listę łaocuchów tekstowych: (Blog BNSIT, Blog Xperios, Google, News). Serwis ma byd
dostępny pod adresem "FeedList".
Instrukcja rozwiązania:
1. Należy stworzyd interfejs
FeedListService dziedziczący po RemoteService I
adnotacją RemoteServiceRelativePath ustawioną na FeedList
2. Dodad do interfejsu metodę getFeedList, która zwraca listę typów tekstowych
3. Stworzyd interfejs o nazwie FeedListServiceAsync z metodą o nazwie getFeedList,
która nie zwraca nic i przyjmuje jedynie jako parametr funkcję zwrotną listy typów
tekstowych
interface
UserListAsync {
public
void
updateUserName(Long id, String user, AsyncCallback<Void>
callback);
public
void getUserName(Long id, AsyncCallback<String> callback);
public
void getUserNameListByFilter(String filter, AsyncCallback<
List<String>> callback);
}
www.devcastzone.com
3
4. Stworzyd klasę FeedService, która dziedziczy po RemoteServiceServlet i implementuje
FeedListService
5. W stworzonej klasie należy zaimplementowad metodę getFeedList
6. W implementacji należy stworzyd obiekt listy, do której należy dodad kolejno „Blog
BNSIT”, „Blog Xperios”, „Google”, „News”, który następnie należy zwrócid.
Rozwiązanie:
@RemoteServiceRelativePath(
"FeedList"
)
interface
FeedListService
extends
RemoteService {
public
List<String> getFeedList();
}
interface
FeedListServiceAsync {
public
void
getFeedList(AsyncCallback<List<String>> callback);
}
class
FeedService
extends
RemoteServiceServlet
implements
FeedListService {
@Override
public
List<String> getFeedList() {
ArrayList<String> out =
new
ArrayList<String>();
out.add(
"Blog BNSIT"
);
out.add(
"Blog Xperios"
);
out.add(
"Google"
);
out.add(
"News"
);
return
out;
}
}
www.devcastzone.com
4
Ćwiczenie 4: DTO
Treść:
Stworzyd model persystencyjny, który za pomocą metody DTO pozwoli na wprowadzenie
danych w części klienckiej, zapisanie ich w bazie danych oraz pobranie ich i wysłanie z
powrotem. Należy stworzyd model persystencyjny Person, który będzie posiadał właściwości
id, name i dateOfBirth oraz releatedList jako listę osób spokrewnionych. Obiekty tego
modelu muszą byd zapisywalne w bazie danych za pomocą Hibernate a także z niej
odczytywane.
Należy opracowad metodę komunikacyjną, pozwoli na przesłanie danych z części klienckiej i
zapisanie ich do bazy danych. Po poprawnym zapisie danych ma zostad pobrana lista
wszystkich elementów modelu i odesłana do klienta.
Instrukcja rozwiązania:
1. .Należy stworzyd model danych Person z adnotacją @Entity i nad właściwościami
pododawad adnotacje: @Id nad identyfikatorem, @Temoral nad polem daty,
@OneToMany nad polem listy.
2. Stworzyd model dto o nazwie PersonDTO, który posiada te same właściwości co do
typów i nazw bez żadnej adnotacji.
3. Do klasy Person dodad statyczne metody pozwalające na konwersję obiektów
PersonDTO do Person i na odwrót
4. Stworzyd plik konfiguracyjny Hibernate wraz z dodanym wpisem mapping class ze
wskazaniem na klasę Person
5. Stworzyd klasę pomocniczą HibernateUtil, która skonfiguruje Hibernate a także
pozwoli na pobranie obiektu sesji.
6. Stworzyd interfejs synchroniczny wraz z metodą: persistAndGetAllPerson, która
przyjmowad będzie obiekt PersonDTO, natomiast zwracad będzie List<PersonDTO>
7. Stworzyd interfejs asynchroniczny
8. Dodad odpowiednie mapowanie w pliku web.xml
9. Stworzyd implementację serwisu, która pozwoli na zainicjonowanie danych w bazie
danych
10. Implementacja metody powinna umożliwiad konwersję obiektów PersonDTO na
obiekty klasy Person, zapis obiektu Person do bazy, odczyt wszystkich elementów
Person z bazy, konwersję wszystkich zwróconych elementów do PersonDTO oraz
odesłanie danych do klienta.
Rozwiązanie:
www.devcastzone.com
5
Model danych:
package
pl.bnsit.rpc.server;
import
java.util.ArrayList;
import
java.util.Date;
import
java.util.List;
import
javax.persistence.CascadeType;
import
javax.persistence.Entity;
import
javax.persistence.FetchType;
import
javax.persistence.GeneratedValue;
import
javax.persistence.GenerationType;
import
javax.persistence.Id;
import
javax.persistence.OneToMany;
import
javax.persistence.Temporal;
import
javax.persistence.TemporalType;
import
pl.bnsit.rpc.shared.PersonDTO;
@Entity
public
class
Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String name;
@Temporal(TemporalType.DATE)
Date dateOfBirth;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
List<Person> relativeList;
public
Person() {
}
public
Person(Long id, String name, Date dateOfBirth,
List<Person> relativeList) {
this
.id = id;
this
.name = name;
this
.dateOfBirth = dateOfBirth;
this
.relativeList = relativeList;
}
//setters and getters
@Override
public
String toString() {
return
"Person{"
+
"id="
+ id +
", name="
+ name +
",
dateOfBirth="
+ dateOfBirth +
", relativeList="
+ relativeList +
'}'
;
}
www.devcastzone.com
6
DTO:
Metody konwertujące zawarte w klasie Person.java:
package
pl.bnsit.rpc.shared;
import
java.util.Date;
import
java.util.List;
public
class
PersonDTO {
Long id;
String name;
Date dateOfBirth;
List<PersonDTO> relativeList;
public
PersonDTO() {
}
public
PersonDTO(Long id, String name, Date dateOfBirth,
List<PersonDTO> relativeList) {
this
.id = id;
this
.name = name;
this
.dateOfBirth = dateOfBirth;
this
.relativeList = relativeList;
}
// getters and setters
@Override
public
String toString() {
return
"PersonDTO{"
+
"id="
+ id +
", name="
+ name +
",
dateOfBirth="
+ dateOfBirth +
", relativeList="
+ relativeList +
'}'
;
}
}
public
static
PersonDTO convertToDto(Person object) {
if
(object ==
null
) {
return
null
;
}
PersonDTO out =
new
PersonDTO();
out.setId(object.getId());
out.setName(object.getName());
out.setDateOfBirth(object.getDateOfBirth());
out.setId(object.getId());
List<Person> relativeListObject = object.getRelativeList();
if
(relativeListObject ==
null
) {
return
out;
}
List<PersonDTO> relativeListDTO =
new
ArrayList<PersonDTO>();
for
(Person person : relativeListObject) {
relativeListDTO.add(convertToDto(person));
}
out.setRelativeList(relativeListDTO);
return
out;
}
}
www.devcastzone.com
7
Przykładowy plik konfiguracyjny hibernate:
HibernateUtil:
public
static
Person convertFromDto(PersonDTO dto) {
if
(dto ==
null
) {
return
null
;
}
Person out =
new
Person();
out.setId(dto.getId());
out.setName(dto.getName());
out.setDateOfBirth(dto.getDateOfBirth());
out.setId(dto.getId());
List<PersonDTO> relativeListDto = dto.getRelativeList();
if
(relativeListDto ==
null
) {
return
out;
}
List<Person> relativeList =
new
ArrayList<Person>();
for
(PersonDTO personDTO : relativeListDto) {
relativeList.add(convertFromDto(personDTO));
}
out.setRelativeList(relativeList);
return
out;
}
}
<?
xml
version=
"1.0"
encoding=
"UTF-8"
?>
<!
DOCTYPE
hibernate-configuration
PUBLIC
"-//Hibernate/Hibernate
Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-
3.0.dtd"
>
<
hibernate-configuration
>
<
session-factory
>
<
property
name=
"hibernate.dialect"
>
org.hibernate.dialect.DerbyDialect
</
prop
erty
>
<
property
name=
"hibernate.connection.driver_class"
>
org.apache.derby.jdbc.Cl
ientDriver
</
property
>
<
property
name=
"hibernate.connection.url"
>
jdbc:derby://localhost:1527/sampl
e
</
property
>
<
property
name=
"hibernate.connection.username"
>
app
</
property
>
<
property
name=
"hibernate.connection.password"
>
app
</
property
>
<
property
name=
"hibernate.current_session_context_class"
>
thread
</
property
>
<
property
name=
"hibernate.hbm2ddl.auto"
>
create-
drop
</
property
>
<
mapping
class=
"pl.bnsit.rpc.server.Person"
/>
</
session-factory
>
</
hibernate-configuration
>
www.devcastzone.com
8
Interfejs synchroniczny:
package
pl.bnsit.rpc.server;
import
org.hibernate.cfg.AnnotationConfiguration;
import
org.hibernate.SessionFactory;
/**
* Hibernate Utility class with a convenient method to get
Session Factory
* object.
*/
public
class
HibernateUtil {
private
static
final
SessionFactory sessionFactory;
static
{
try
{
// Create the SessionFactory from standard
(hibernate.cfg.xml)
// config file.
sessionFactory =
new
AnnotationConfiguration().configure().buildSessionFactory();
}
catch
(Throwable ex) {
// Log the exception.
System.err.println(
"Initial SessionFactory creation
failed."
+ ex);
throw
new
ExceptionInInitializerError(ex);
}
}
public
static
SessionFactory getSessionFactory() {
return
sessionFactory;
}
}
package
pl.bnsit.rpc.client;
import
com.google.gwt.user.client.rpc.RemoteService;
import
com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import
java.util.List;
import
pl.bnsit.rpc.shared.PersonDTO;
@RemoteServiceRelativePath(
"PersonService"
)
public
interface
PersonListService
extends
RemoteService {
public
List<PersonDTO> persistAndGetAllPerson(PersonDTO
person);
}
www.devcastzone.com
9
Interfejs asynchroniczny:
Mapowanie serwletu:
Implementacja serwisu:
package
pl.bnsit.rpc.client;
import
com.google.gwt.user.client.rpc.AsyncCallback;
import
java.util.List;
import
pl.bnsit.rpc.shared.PersonDTO;
public
interface
PersonListServiceAsync {
public
void
persistAndGetAllPerson(PersonDTO person,
AsyncCallback<List<PersonDTO>> callback);
}
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
web-app
version
=
"2.4"
xmlns
=
"http://java.sun.com/xml/ns/j2ee"
xmlns:web
=
"http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
=
"http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
<
servlet
>
<
servlet-name
>
PersonService
</
servlet-name
>
<
servlet-class
>
pl.bnsit.rssreader.server.FeedServiceImpl
</
servlet-
class
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>
PersonService
</
servlet-name
>
<
url-pattern
>
/MainModule/ PersonService
</
url-pattern
>
</
servlet-mapping
>
<
servlet
>
<
servlet-name
>
PersonService
</
servlet-name
>
<
servlet-class
>
pl.bnsit.rpc.server.PersonListServiceImpl
</
servlet-
class
>
</
servlet
>
<
welcome-file-list
>
<
welcome-file
>
MainModule.html
</
welcome-file
>
</
welcome-file-list
>
</
web-app
>
www.devcastzone.com
10
package
pl.bnsit.rpc.server;
import
com.google.gwt.user.server.rpc.RemoteServiceServlet;
import
pl.bnsit.rpc.client.PersonListService;
import
java.util.ArrayList;
import
java.util.Date;
import
java.util.List;
import
org.hibernate.Transaction;
import
org.hibernate.classic.Session;
import
pl.bnsit.rpc.shared.PersonDTO;
public
class
PersonListServiceImpl
extends
RemoteServiceServlet
implements
PersonListService {
static
{
System.out.println(
"Initializing person data"
);
Session session =
HibernateUtil.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
transaction.begin();
List<Person> personList =
new
ArrayList<Person>();
personList.add(
new
Person(
null
,
"Sister"
,
new
Date(),
null
));
personList.add(
new
Person(
null
,
"Brother"
,
new
Date(),
null
));
personList.add(
new
Person(
null
,
"Me"
,
new
Date(),
null
));
session.save(
new
Person(
null
,
"Father"
,
new
Date(),
personList));
transaction.commit();
}
@Override
public
List<PersonDTO> persistAndGetAllPerson(PersonDTO
person) {
Session session =
HibernateUtil.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
transaction.begin();
session.save(Person.convertFromDto(person));
transaction.commit();
return
getPersonDto();
}
public
static
List<Person> getPersonList() {
Session session =
HibernateUtil.getSessionFactory().openSession();
return
session.createCriteria(Person.
class
).list();
}
public
static
List<PersonDTO> getPersonDto() {
List<PersonDTO> out =
new
ArrayList<PersonDTO>();
for
(Person person : getPersonList()) {
out.add(Person.convertToDto(person));
}
return
out;
}
}
www.devcastzone.com
11
Częśd kliencka (wywołująca):
package
pl.bnsit.rpc.client;
import
com.google.gwt.core.client.EntryPoint;
import
com.google.gwt.core.client.GWT;
import
com.google.gwt.user.client.Window;
import
com.google.gwt.user.client.rpc.AsyncCallback;
import
com.sencha.gxt.widget.core.client.box.MessageBox;
import
java.util.Date;
import
java.util.List;
import
pl.bnsit.rpc.shared.PersonDTO;
public
class
MainModule
implements
EntryPoint{
@Override
public
void
onModuleLoad() {
PersonListServiceAsync service =
GWT.create(PersonListService.
class
);
PersonDTO person =
new
PersonDTO(
null
,
"Me"
,
new
Date(),
null
);
service.persistAndGetAllPerson(person,
new
AsyncCallback<List<PersonDTO>>() {
@Override
public
void
onFailure(Throwable caught) {
Window.alert(
"error occured: "
+caught.getMessage());
}
@Override
public
void
onSuccess(List<PersonDTO> result) {
Window.alert(
"People in db: I"
+result.size()+
""
);
}
});
}
}