poniedziałek, 28 kwietnia 2014

Java.Collections - Podstawy.

Kilka słów wprowadzenia...


Na wstępie zaznaczam, że jest to artykuł dla początkujących programistów Javy, lecz pojęcia takie jak interfejs czy podstawowe struktury danych nie powinny być czytelnikowi obce.
W poniższym artykule chciałbym omówić temat wbudowanych kolekcji w języku Java. Każdy adept programowania prędzej czy później spotka się z tym zagadnieniem, dlatego przybliżę czym są kolekcje i jakie są ich rodzaje. Po wstępie teoretycznym postaram się jasno pokazać jak się je definiuje oraz przedstawić proste przykłady ich wykorzystania.
Kolekcje to inaczej mówiąc kontenery na dane. Mogą przechowywać dowolne typy danych – zarówno wbudowane jak i zdefiniowane przez programistę. Zależnie od rodzaju posiadają różne właściwości takie jak możliwość duplikacji czy porządkowania danych. Aby zobrazować interfejsy z jakich wywodzą się niżej przedstawione kolekcje posłużę się schematem (wybaczcie prostotę - mój talent designerski nie jest na wysokim poziomie).

Każda z pokazanych implementacji (ArrayList, LinkedList, PriorityQueue, HashSet, TreeSet, HashMap, TreeMap) znajduje się w standardowym pakiecie „java.utils”. Jak można zauważyć implementacje list, kolejek(Queue) i zbiorów(Set) pochodzą ze wspólnego interfejsu Collection, natomiast mapy pochodzą z osobnego interfejsu.

Podstawowe metody interfejsu Collection:

add(E element)
remove(Object O)
size() – zwraca ilość elementów listy.
clear() – usuwa wszystkie elementy listy.

Listy


Najprostszymi i jednymi z najczęściej używanych kontenerów są listy. Jej elementy są uporządkowane (porządek oznacza, że wszystkie elementy są dostępne w takiej samej kolejności jak je dodaliśmy i posiadają relacje pomiędzy sąsiadami) oraz mają możliwość duplikacji w przestrzeni jednej listy.

Podstawowe operacje na listach:

add(int index,E element) – dodaje nowy element do listy.
remove(int index) – usuwa określony element z listy.
get(int index) – zwraca określony element listy.
indexOf(Object o) – zwraca indeks określonego obiektu w liście (jeśli taki istnieje).



Podstawowe operacje na listach w praktyce:

Wyniki działania programu w konsoli:

Liczba elementów listy: 6
Liczba elementów listy po usunięciu jednego z elementów: 5
Zwrócenie ostatniego elementu listy: Kamil


Kolejki


Kolejka jest jedną z podstawowych struktur danych. W zależności od implementacji elementy są dodawane i zwracane w różnej kolejności (LIFO,FIFO). LinkedList, która wykorzystuje zarówno interfejs List jak i Queue jest implementacją kolejki FIFO. W kolejkach mamy bezpośredni dostęp do pierwszego elementu – głowy, a reszta elementów tworzy ogon. Po usunięciu głowy, staje się nią pierwszy element ogona.

Podstawowe operacje na kolejkach:

offer(Object o) – dodaje element do kolejki.
poll() – zwraca głowę kolejki i usuwa ją.
peek() – zwraca głowę kolejki bez usuwania jej.



Podstawowe operacje na kolejkach w praktyce:

Wyniki działania programu w konsoli:
Liczba elementów kolejki: 6
Głowa kolejki :Jakub
Liczba elementów kolejki: 5
Zwrócenie kolejnej głowy kolejki: Kamil
Liczba elementów kolejki: 5


Zbiory


Zbiór jest kolekcją w której elementy są nieuporządkowane (nie istnieje żadna relacja między dwoma elementami zbioru). Ważną cechą zbioru jest również wykluczenie duplikatów – nie można przechowywać dwóch tych samych obiektów w przestrzeni jednego zbioru. Zbiory nie posiadają żadnych dodatkowych metod, poza tymi odziedziczonymi z interfejsu Collection.

Przykład pokazujący zachowanie zbioru przy próbie dodania duplikatu:

Wyniki działania programu w konsoli:
true
true
true
false
Liczba elementów zbioru: 3



Mapy


Mapy są kolekcją której elementy składają się z klucza i wartości. Wartości mogą się powtarzać, lecz klucze muszą być unikalne, nie ma możliwości przypisania dwóch wartości do jednego klucza.

Podstawowe operacje na mapach:
clear() – czyści całą mapę z wartości i kluczy.
containsKey(Object key) – Sprawdza czy dany klucz znajduje się w mapie.
containsValue(Object value) – Sprawdza czy dana wartość znajduje się w mapie.
get(Object key) - Zwraca wartość do której jest przypisany dany klucz.
put(K key, V value) – Wprowadza element (klucz - wartość) do mapy.
remove(Object key) – Usuwa wartość (i klucz) do którego przypisany jest klucz.
size() - Zwraca ilość elementów (par klucz – wartość) w mapie.


Podstawowe operacje na mapach w praktyce:

Wyniki działania programu w konsoli:
Ilość elementów w mapie: 4
Wartość dla klucza "Kamil": 150
Wartość dla klucza "Kamil": 200
Ilość elementów w mapie: 0



To wszystko co chciałem przedstawić w powyższym artykule. Temat kolekcji jest dość popularny i jego odkrywczość można porównać do odgrzewanych kotletów, jednakże nawet w odgrzanym kotlecie można odnaleźć rąbek smaku jeśli tylko odbiorca jest głodny (wiedzy). :-)


Źródła:
http://docs.oracle.com/javase/tutorial/collections/
http://wazniak.mimuw.edu.pl/images/3/32/Zpo-2-wyk.pdf

poniedziałek, 21 kwietnia 2014

Podstawy Apache Struts 2

W tym artykule postaram się przedstawić użycie technologii Apache Struts 2.

Pierwszym krokiem będzie stworzenie serwera Apache tomcat. W tym celu z menu widoku Servers wybieramy New-Server.


Jeśli w liście rozwijanej Server runtime environment nie mamy do wyboru serwera, musimy go dodać klikając Add, a następnie wskazać lokalizację serwera.

Następnym krokiem będzie stworzenie projektu aplikacji. Wchodzimy w File-New-Dynamic Web Project


Ustawiamy konfigurację jak wyżej. Następnie w WebContent-WEB-INF-lib dodajemy pliki jar:


Kolejnym krokiem jest stworzenie klasy, która będzie naszą akcją.  

package com.blogspot.justdiscoverit;

public class LoginAction {
	private String username;
	private String password;

	public String execute() {

		if (this.username.equals("Admin") && this.password.equals("admin1")) {
			return "success";
		} else {
			return "error";
		}
	}

	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;
	}
}
W powyższej klasie mamy dwa pola, oraz metody get i set do każdego z nich. Ponadto mamy także metodę execute() w której sprawdzamy, czy pola mają odpowiednie wartości i w zależności od wyniku zwracamy wartość String "success" albo "error". Teraz potrzebujemy dwa pliki: Login.jsp oraz Welcome.jsp:

Login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<body>
<s:form action="login" method="post">
<s:textfield name="username" key="label.username" />
<s:password name="password" key="label.password" />
<s:submit method="execute" key="label.login" />
</s:form>
</body>
</html>

Welcome.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<body>
<h2>
Hello <s:property value="username" /> !
</h2>
</body>
</html>

Ważne jest, aby w każdym pliku znajdował się kod:

<%@ taglib prefix="s" uri="/struts-tags"%>

Plik Welcome.jsp jest bardzo prosty, pobiera on tylko wartość pola username poprzed wywałanie metody getUsername() z klasy LoginAction.

W pliku Login.jsp w znaczniku form znajduje się wpis action="login" dzięki któremu zostanie dopasowana odpowienia klasa zdefiniowana w pliku struts.xml

Następnie dodajemy do projektu New-Source Folder i nadajemy mu nazwę resources. W dodajemy tam plik o nazwie ApplicationResources.properties a w jego zawartości umieszczamy:

label.username= User

label.password= Password

label.login= Login
Wartości te będą wykorzystywane w plikach JSP.

W tym samym katalogu tworzymy plik struts.xml i umieszczamy w nim następujący kod:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
        <constant name="struts.devMode" value="false" />
<constant name="struts.custom.i18n.resources" value="ApplicationResources" />

<package name="default" extends="struts-default">
<action name="login" class="com.blogspot.justdiscoverit.LoginAction">
<result name="success">Welcome.jsp</result>
<result name="error">Login.jsp</result>
</action>
</package>
</struts>

Wszystkie definiowane wpisy trzeba umieszczać w <struts> .. </struts>. Możemy tam definiować pakiety, a w nich definiować nowe akcje. Mamy tutaj zdefiniowaną akcję o nazwie login oraz zdefiniowane odwołanie do klasy, która jest przypisana do tej nazwy, czyli w tym przypadku klasa LoginAction. Mamy zdefiniowane także możliwe rezultatu działania tej akcji - success oraz error - i w zależności od wyniku działania zostaniemy przekierowani do pliku Welcome.jsp lub Login.jsp.

Ostatnim krokiem jest edycja pliku web.xml znajdującego się w WebContent-WEB-INF. Jeśli go tam nie ma, należy go stworzyć i umieścić następujący kod:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    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">

    <display-name>Struts2 Application</display-name>
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>Login.jsp</welcome-file>
    </welcome-file-list>

</web-app>

Po uruchomieniu naszej aplikacji na serwerze i wpisaniu http://localhost:8080/Struts2/Login.jsp otrzymamy formularz do logowania:


Jeśli wpiszemy wartości, które będą zgadzały się z tymi zdefiniowanymi w klasie LoginAction, zostaniemy przekierowaniu do Welcome.jsp i w wyniku otrzymamy:


To wszystko :) Mam nadzieję, że udało mi się choć trochę przybliżyć działanie technologii Apache Struts2.

sobota, 19 kwietnia 2014

Consuming REST services via Apache HTTP Client - Wprowadzenie do HTTP i REST


1.    Protokół HTTP

HTTP jest protokołem określającym standard przesyłania dokumentów WWW. Wykorzystuje on protokół TCP zazwyczaj wykorzystując port 80.
Standard protokołu HTTP określa norma:
RFC 2616 Hypertext Transfer Protocol -- HTTP/1.1
  • HTTP model komunikacji:
Wielu klientów - jeden serwer
 
Wielu klientów otrzymuje zasób udostępniany przez jeden serwer. Teoretycznie serwis WWW, może być rozproszony na wielu hostach, jednak zawsze na końcu przekierowań mamy jeden adres docelowy.  

  • HTTP szablon komunikacji
 
  • Własności protokołu HTTP
 
Protokół HTTP jest protokołem transmitującym dane tekstowe (zdarzają się również elementy binarne). Każda odpowiedź serwera jest oznaczona odpowiednim kodem. Należy również zaznaczyć, że w protokole HTTP komunikację zawsze inicjuje klient.
  • Miejsce HTTP w modelu ISO/OSI - warstwa aplikacji
 
  • Metody protokołu HTTP -

W zależności od potrzeb protokół HTTP umożliwia nam wykorzystanie kilku metod:

  •    HTTP Request
Każde zapytanie wysłane do serwera musi posiadać odpowiednią strukturę.

a)      Typ metody żądania i jej parametry
b)      Nagłówek żądania (nazwa hosta docelowego, typ i długość przesyłanych danych (POST) , typ przeglądarki, ciasteczka, poprzednia strona)
c)      Pusta linia
d)      Treść danych przesyłanych do serwera (opcjonalnie)

GET /path/file.html HTTP/1.0
From: someuser@jmarshall.com
User-Agent: HTTPTool/1.0
[blank line here]
  • HTTP Response
Struktura odpowiedzi serwera jest następująca:

a)      Wersja protokołu, kod błędu, opis kodu

b)      Nagłówek odpowiedzi (czas serwera, informacje o serwerze, ciasteczka, informacje o typie zasobu i jego długości)

c)      Pusta linia
            d)    Treść danych przesyłanych przez serwer
HTTP/1.0 200 OK
Date: Fri, 31 Dec 1999 23:59:59 GMT
Content-Type: text/html
Content-Length: 1354

<html>
<body>
<h1></h1>
(more file contents)
  .
  .
  .
</body>
</html>
  • Najważniejsze metody HTTP – POST i GET 
Metoda POST:
- wysyła dane do zasobu url do dalszego przetwarzania. Najczęściej do formularzy
- dane przesyłane w treści żądania
- służy do wysyłania nowych bądź aktualizacji bieżących zasobów

Metode GET:
- pobiera z serwera zasób opisany poprzez URL
  • Kody błędów

Każdy programista powinien znać zakres kodów błędów w komunikacji serwer – klient.





2.    REST

REST – Representional State Transfer jest architekturą projektowania sieciowych aplikacji. Polega on na użyciu komunikacji stateless – która traktuje każdy request jako osobną transakcje. Używa on komunikacji typu klient- serwer. REST komunikuje się protokołem HTTP.

REST jest alternatywą dla innych ciężkich mechanizmów przesyłania danych poprzez sieć( CORBA,RPC,SOAP). Umożliwia wykonywanie wszystkich operacji CRUD.
Należy zauważyć, że REST nie jest standardem.

3.    Sniffing HTTP requests/response


Sniffer Wireshark umożliwia nam podglądnięcie struktury żądania/odpowiedzi poprzez protokół HTTP. Aby to ułatwić, możemy skrozystać z odpowiednich filtrów. 
Uruchamiamy program Wireshark i w opcji filtra aby pokazać requesty:

 
Wpisujemy: 


http.request.method == GET or http.request.method == POST
 
Aby odfiltrować odpowiedzi:
http.response

Znając RC możemy też użyć

http.response.code=kod

Odpowiednie wyniki metody GET do www.wp.pl  są następujące:
a) request

 

b) response

 

4.    Struktura bibliotek Apache HTTPComponents


Apache HTTP Client jest częścią projektu Apache HttpComponents. Jest on odpowiedzialny za tworzenie I utrzymanie niskopoziomowego API Javy stworzonego dla obsługi protokołów HTTP oraz protokołów z nim powiązanych.
W chwili obecnej najnowszym GA jest build 4.3.3.

Projekt Apache HTTPComponents składa się z kilku części:

4.1.      HttpComponents Core

Zawiera zestaw niskopoziomowych bibliotek, do budowy zarówno serwera jak I klienta usług HTTP .  HttpCore wspiera 2 modele budowy aplikacji typu I/O w języku Java
1.1.   Blokujący model I/O bazujący na standardowych bibliotekach I/O
1.2.   Nieblokujący model I/O sterowany zdarzeniami bazujący na java NIO

Do budowy aplikacji z intensywnymi, mało opóźniającymi scenariuszami wymiany danych zaleca się pierwszy z modeli, natomiast z drugiego z modeli korzystamy gdy zależy nam bardziej na możliwości otrzymania dużej ilości połączeń w efektywny sposób

4.2.      HttpComponents Client

Jest to implementacja agenta protokołu HTTP/1.1 bazująca na HTTPCore. Dostarcza komponentów umożliwających autentykację, śledzenie stanu oraz zarządzanie połęczeniem poprzez protokół HTTP.

4.3.      HttpComponents AsyncClient


Jest to implementacja agenta protokołu HTTP/1.1 bazująca na bibliotekach HttpCore NIO oraz HttpCore.  Komponent ten, używamy gdy musimy odebrać dużą liczbę połączeń, stawiając na drugim miejscu perfrormance

4.4.      Commons HttpClient

Moduł ten stał się ostatnio deprecated. Użytkownikom Commons HttpClient zaleca się migrację do HttpComponents Client

5.    Biblioteki oraz dokumentacja Apache HTTP Client

Wszystkie biblioteki Apache HTTP Client możemy pobrać korzystając ze strony:
Możliwe jest również dodanie dependencji w pliku POM.

Na stronie: https://hc.apache.org/ znajdziemy również bogaty zestaw tutoriali oraz dokumentację.


Pora zatem przejść do pracy i przesłać nasz pierwszy request.

6.    Aplikacja

Po stworzeniu projektu Mavena, bez wyboru archetypu, możemy dodać dependencję do bibliotek Apache HttpClient. W tym celu w pliku POM.xml dodajemy:


<dependency> 
 <groupId>org.apache.httpcomponents</groupId>
 <artifactId>httpClient</artifactId>>
 <version>4.3.3</version>
</dependency> 


Następnie możemy napisać klasę realizującą wywołanie metody HTTPGet dla www.wp.pl

package com.justdiscoverit.blogstpot;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class TestApacheHttpClient {

    public static void main(String... strings) {
        // CloseableHttpClient - klasa bezpieczna watkowo
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet("http://www.wp.pl");
        CloseableHttpResponse response1 = null;
        try {
            response1 = httpclient.execute(httpGet);

            // polaczenie HTTP jest utrzymywane przes obiekt odnoszacy sie
            // do referencji response1. Aby zamknac poprawnie polaczenie
            // i zwolnic zasoby nalezy wywolac metode consume z klasy
            // EntityUtils lub przerwac wykonywanie metoda close

            // czytamy kod odpowiedzi serwera
            System.out.println(response1.getStatusLine());
            HttpEntity entity1 = response1.getEntity();

            // czytamy content odpowiedzi HttpGet linia po linii
            BufferedReader rd = new BufferedReader(new InputStreamReader(
                    entity1.getContent()));
            String line = "";
            StringBuffer sb = new StringBuffer();
            while ((line = rd.readLine()) != null) {
                sb.append(line + "\n");
            }

            System.out.println(sb);

            // zamykamy polaczenie
            EntityUtils.consume(entity1);
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                response1.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
} 
 
Po wykonaniu powyższego programu dostajemy output na consoli:

HTTP/1.1 200 OK
<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="utf-8">
    <title>Wirtualna Polska - www.wp.pl</title>
    <meta name="Expires" content="0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta http-equiv="X-XRDS-Location" content="http://serwer.openid.wp.pl/?xrds=1">
    <meta name="author" content="Wirtualna Polska">
    <meta name="keywords" content="wp.pl,wp,Wirtualna Polska,Wirtualna,Polska,Katalog,Katalog WWW,Firmy,Encyklopedia,Pogoda,Wiadomosci,Program,Telewizja,Sklep,Kawiarenka,MP3">
    <meta name="description" content="Pierwszy horyzontalny portal internetowy w Polsce. Skuteczne medium reklamowe. Bogactwo serwisow informacyjnych i finansowych. Centrum wyszukiwania, komunikacji i rozrywki: wiadomosci, wyszukiwarki, poczta, webpark, czat, komunikator, SMS, randki, kartki, krzyĹĽĂłwki, mp3, gry, gry on-line, muzyka, film. Platforma e-commerce: aukcje, zakupy, przetargi, oferty, turystyka.">
    <meta name="robots" content="index,follow">
    <meta property="og:image" content="http://x.wpimg.pl/i/ivar/layout/201201/logo_wppl_1200x630.png">
    <meta http-equiv="X-UA-Compatible" content="IE=10">
.....

Teraz omówimy poszczególne fragmenty kodu:
CloseableHttpClient httpclient = HttpClients.createDefault();
Klasa CloseableHttpClient jest  klasą implementującą interfejsy Closeable, AutoCloseable oraz HTTPClient.Implementacja 2 pierwszych interfejsów sprawia, że klasa ta jest uważana za klasę reprezentującą zasoby zewnętrzne. Oznacza to, że zasoby powinny być zwalniane metodą close(). Różnica pomiędzy intefejsami AutoCloseable i Closeable jest taka, że metoda close() intefejsu Closeable może wyrzucać jedynie wyjątek typu IOException natomiast metoda close() interfejsu AutoCloseable może wyrzucać wyjątek dowolnego typu. Interfejs Closeable stanowi rozszerzenie interfejsu AutoCloseable. Klasa HttpClients jest specjalną klasą posiadającą prywatny konstruktor. Posiada ona kilka statystycznych metod umożliwiających stworzenie obiektu typu CloseableHttpClient z predefiniowanymi ustawieniami.
CloseableHttpResponse response1 = null;
CloseableHttpResponse jest intefejsem implementującym również interfejsy AutoCloseable, Closeable jak również interfejsy HttpMessage, HttpResponse.  
response1 = httpclient.execute(httpGet);
Metoda execute klasy CloseableHttpClient wykonuje zapytanie, oraz zwraca referencję do obiektu implementującego interfejs CloseableHttpResponse.
 System.out.println(response1.getStatusLine());
Za pomocą metody getStatusLine() możemy otrzymać RC oraz opis kodu, np:HTTP/1.1 200 OK
HttpEntity entity1 = response1.getEntity();
 Metoda getEntity() zwraca obiekt HttpEntity będący abstrakcyjną reprezentacją żądań bądź odpowiedzi. Składa się z nagłowka oraz opcjonalnie z ciała.
 BufferedReader rd = new BufferedReader(new InputStreamReader(
                    entity1.getContent()));
Za pomocą metody getContent() otrzymujemy obiekt klasy InputStream, który następnie wykorzystujemy do przeczytania odpowiedzi serwera. 
 EntityUtils.consume(entity1);
 Aby zwonić zasoby należy użyć metody statycznej consume klasy EntityUtils. W klauzuli finally zawarte jest jeszcze wywołanie 
response1.close();
Dzięki niemu możemy mieć pewność, że nawet podczas wystąpienia wyjątku zasoby zostaną zwolnione.  

W kolejnej części  pokażę zastosowanie Apache HTTPClient w kooperacji z Google Calendar.

Źródła:
http://tjaworski.kis.p.lodz.pl/zajecia/ps2/HTTP.pdf
https://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/
http://www.jmarshall.com/easy/http/#sample