Struktura aplikacji korzystającej z SIP Servlet jest bardzo podobna do struktury aplikacji webowej (opartej o HTTP Servlet). Możliwe jest nawet łączenie servlet'ów SIP i HTTP w jednej aplikacji. Właściwie jedyna różnica polega na tym, że komponenty SIP Servlet są definiowane przy użyciu deployment descriptor'a sip.xml, a komponenty HTTP Servlet za pomocą web.xml (i opcjonalnie deployment descriptor'ów specyficznych dla kontenera - ale tylko dla web.xml, bo specyfikacja SIP Servlet API takich "specyficznych" deployment descriptor'ów nie wprowadza). W tym podejściu widać jedno z głównych założeń SIP Servlet, czyli maksymalne powtórne wykorzystanie znanych już i sprawdzonych od lat sposobów pracy dewelopera, narzędzi, koncepcji, itd. Programiści są też niemal "zachęcani" do tworzenia usług (aplikacji) konwergentnych, tj. takich w których np. dostęp poprzez web miesza się z dostępem poprzez telefon albo w ramach usług telekomunikacyjnych korzysta się z bogatych treści internetowych lub usług systemów IT.
Nic zatem dziwnego, że do budowy aplikacji SIP Servlet, w dużym stopniu można użyć narzędzi do tworzenia aplikacji webowych i np. w Eclipse IDE użyć tego samego wizard'a do tworzenia struktury aplikacji (Dynamic Web Project). A zatem, z menu głównego Eclipse, wybieramy File -> New -> Dynamic Web Project. Na wyświetlonym ekranie należy podać nazwę projektu (np. helloSIPServlet). Pozostałe opcje są OK, należy zatem nacisnąć przycisk Next:

Parametry domyślne na kolejnym ekranie są OK (choć pewnie warto użyć konwencji Maven'a), więc można nacisnąć przycisk Finish:

Zostanie utworzona następująca (pusta) struktura aplikacji:

Aby móc skorzystać z SIP Servlet API, należy dodać stosowne biblioteki (JAR). W tym celu należy z menu kontekstowego projektu wybrać Properties, a następnie zaznaczyć sekcję Java Build Path i przejść na zakładkę Libraries:

Zdefiniuję nową bibliotekę (User Library), w której zawarte będą odpowiednie pliki JAR. Należy zatem nacisnąć przycisk Add Library, a na wyświetlonym ekranie zaznaczyć opcję User Library i nacisnąć przycisk Next:

Na kolejnym ekranie należy nacisnąć przycisk User Libraries:

Na kolejnym ekranie należy nacisnąć przycisk New:

W wyświetlonym oknie dialogowym podać nazwę biblioteki (np. OCCAS 4.0) i nacisnąć przycisk OK:

Następnie należy zaznaczyć nazwę nowo-utworzonej biblioteki i nacisnąć przycisk Add JARs:

Należy przejść do folderu: [BEA_HOME] \ wlcserver_10.3 \ server \ lib \ wlss i zaznaczyć pliki (można użyć klawisza CTRL do wybrania od razu dwóch plików):
- sipservlet.jar
- wlss.jar
Po naciśnięciu przycisku OK, te pliki JAR zostaną dodane do biblioteki. Należy jeszcze zadbać o właściwą ich kolejność - plik sipservlet.jar powinien być przed plikiem wlss.jar (bo sipservlet.jar zawiera typy określone przez specyfikację SIP Servlet API). Należy zaznaczyć plik sipservlet.jar i użyć przycisku Up, tak, aby ekran wyglądał następująco:

Następnie należy nacisnąć przycisk OK, a potem Finish i jeszcze raz OK.
Głównym komponentem zawierającym logikę przetwarzania komunikatów SIPowych w SIP Servlet jest... servlet. Musimy zatem utworzyć nową klasę (zaznaczyć folder src, a potem wybrać z menu kontekstowego New -> Class. Klasa musi dziedziczyć po javax.servlet.sip.SipServlet:

Zostanie utworzona następująca klasa:
package pl.waldekkot.sip; import javax.servlet.sip.SipServlet; public class MyHelloSIPServletWorld extends SipServlet { }
Mało fascynujące, więc dodajmy jakieś metody - a dokładniej metody obsługujące komunikaty SIP. W SIP chcąc nawiązać połączenie z drugą stroną, klient (np. telefon VoIP) wysyła komunikat INVITE (podobnie jak w HTTP, przeglądarka wysyła komunikat GET). W naszej aplikacji "przechwycimy" ten komunikat i wykonamy kod metody doInvite(). W nim będzie zawarte nieodzowne dla aplikacji typu Hello World wyświetlenie komunikatu "Hello SIP Servlet World" (oczywiście ten komunikat będzie wyświetlony w konsoli serwera - wysyłanie odpowiedzi do klienta SIP będzie przedmiotem dalszych ćwiczeń, gdy pokonamy już z sukcesem etap Hello World ;-).
Należy zatem dodać do klasy, obsługę metody doInvite():
package pl.waldekkot.sip; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.sip.SipServlet; import javax.servlet.sip.SipServletRequest; public class MyHelloSIPServletWorld extends SipServlet { @Override protected void doInvite(SipServletRequest req) throws ServletException, IOException { System.out.println("Hello SIP Servlet World ! Calling: " + req.getTo()); } }
Oprócz komunikatu "Hello SIP Servlet World !" wyświetli się informacja do kogo komunikat INVITE jest kierowany (do kogo "dzwonimy").
Teraz, trzeba zdefiniować jakie komunikaty SIP ma "wychwytywać" kontener (OCCAS) i do którego servlet'u ma je przekierować. W HTTP jest to dosyć łatwe, gdyż HTTP posługuje się pojęciem URL (np. http://localhost:7001/console). SIP posługuje się dosyć podobnym w składni, choć odmiennym znaczeniowo i bardziej "dynamicznym" URI (Uniform Resource Locator), np. sip:waldek.kot@localhost:5061 (trochę upraszczam, ale na tym etapie nie chciałbym zaciemniać szczegółami). Stąd też przypisanie servlet'u w SIP Servlet jest bardziej złożone niż w HTTP Servlet (ale też pozwala opisać znacznie ciekawsze sytuacje). Dla przykładu, w HTTP Servlet przypisalibyśmy dany servlet do określonego kontekstu, np.: \xyz. W SIP Servlet możemy "przypisać" dany servlet np. do obsługi komunikatu INVITE (czyli zawsze, gdy do kontenera SIP zostanie wysłany komunikat INVITE, ten komunikat - jako request - zostanie przekazany do danego servlet'u).
Jak pewnie wszyscy wiedzą - w aplikacjach webowych, przypisanie servlet-URL określa się w pliku web.xml. W aplikacjach SIP Servlet, to przypisanie określa się w pliku sip.xml. Oba te pliki powinny znajdować się w aplikacji w folderze WEB-INF.
Czyli musimy teraz utworzyć plik XML o nazwie sip.xml, który powinien być zgodny ze schematem (XSD) określonym w specyfikacji SIP Servlet API (aktualnie 1.1) i umieścić go w folderze WEB-INF.
Aby sobie trochę życie ułatwić (i na przykład mieć auto-uzupełnianie po CTRL+SPACE), warto skorzystać z możliwości edycji XML w Eclipse IDE. Należy zatem najpierw zaimportować schemat (XSD) opisujący SIP Servlet do katalogu XML Eclipse. Plik schematu znajduje się oczywiście w sipservlet.jar. Należy ten plik (sip-app_1_1.xsd) skopiować z archiwum do oddzielnego folderu (np. C:\OCCAS40\user_projects\sipservlet-xsd).
Następnie należy z menu głównego Eclipse wybrać Window -> Preferences i przejść do sekcji XML -> XML Catalog:

Tu należy nacisnąć przycisk Add. Pojawi się następujący ekran:

Na tym ekranie, za pomocą ikonki przy polu Location należy (z File System'u) wskazać zapisany wcześniej plik schematu (u mnie on jest w: C:\OCCAS40\user_projects\javax\servlet\sip\resources\sipservlet-xsd) i nacisnąć dwukrotnie przycisk OK:

Teraz, należy w zakładce Project Explorer zaznaczyć folder WEB-INF i z menu kontekstowego wybrać New -> Other, a potem XML -> XML i nacisnąć przycisk Next:

Jako nazwę pliku podać sip.xml i upewnić się, że ten plik będzie zapisany w folderze WEB-INF - po tym należy nacisnąć przycisk Next:

Na kolejnym ekranie należy zaznaczyć opcję Create XML file from an XML schema file i nacisnąć przycisk Next:

Na kolejnym ekranie należy wybrać opcję Select XML Catalog entry. Wyświetli się lista zdefiniowanych w IDE schematów - należy odnaleźć zaimportowany wcześniej schemat: http://www.jcp.org/xml/ns/sipservlet. Po tym, nacisnąć przycisk Next:

Na kolejnym ekranie należy w polu Root element ustawić wartość sip-app. Dla przejrzystości, przydatne jest także pozbycie się prefix'u "p" z namespace'u SIP Servlet'u:

Po tych zmianach można nacisnąć przycisk Finish.
Zostanie utworzony plik sip.xml, z pustą zawartością:
<?xml version="1.0" encoding="UTF-8"?> <sip-app xmlns="http://www.jcp.org/xml/ns/sipservlet" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jcp.org/xml/ns/sipservlet http://www.jcp.org/xml/ns/sipservlet "> </sip-app>
Przy okazji widać, że Eclipse pokazuje błąd (o tym, że plik schematu sip-app_1_1.xsd zawiera błędy). Podglądając szczegóły błędu okazuje się, że ten schemat zawiera referencje do innych schematów i brakuje mu plików zawierających ten schemat. Te referencje odnoszą się do schematów zdefiniowanych dla HTTP Servlet'ów. Należy zatem do folderu w którym znajduje się sip-app_1_1.xsd dodać te brakujące pliki. Można je wyciągnąć z pliku javax.servlet_1.0.0.0_2-5.jar, który znajduje się w folderze [BEA_HOME]\modules (u mnie: C:\OCCAS40\modules). Trzeba wyekstraktować następujące pliki XSD:
- javaee_5.xsd
- jsp_2_1.xsd
- web-app_2_5.xsd
- javaee_web_services_client_1_2.xsd
Te pliki trzeba wgrać do tego samego folderu w którym jest sip-app_1_1.xsd (u mnie: C:\OCCAS40\user_projects\sipservlet-xsd\javax\servlet\sip\resources). Po tym, po zapisaniu pliku sip.xml komunikat o błędzie pokazywany przez Eclipse powinien zniknąć. Powinien też poprawnie działać skrót podpowiadania CTRL+SPACE.
Do listy namespace'ów trzeba jeszcze dodać:
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
A zatem poprawny, pusty plik sip.xml powinien wyglądać następująco:
<?xml version="1.0" encoding="UTF-8"?> <sip-app xmlns="http://www.jcp.org/xml/ns/sipservlet" xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jcp.org/xml/ns/sipservlet http://www.jcp.org/xml/ns/sipservlet "> </sip-app>
W deployment descriptorze sip.xml definiujemy:
- nazwę aplikacji
- SIP servlet'y (nazwa + klasa + ew. kolejność ładowania)
- mapowanie SIP servlet'ów
- inne parametry
Dla budowanej aplikacji Hello SIP Servlet World, plik sip.xml powinien wyglądać następująco:
<?xml version="1.0" encoding="UTF-8"?> <sip-app xmlns="http://www.jcp.org/xml/ns/sipservlet" xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jcp.org/xml/ns/sipservlet http://www.jcp.org/xml/ns/sipservlet "> <app-name>hello</app-name> <servlet> <javaee:servlet-name>MyHelloWorld</javaee:servlet-name> <javaee:servlet-class>pl.waldekkot.sip.MyHelloSIPServletWorld</javaee:servlet-class> </servlet> <servlet-selection> <servlet-mapping> <servlet-name>MyHelloWorld</servlet-name> <pattern> <equal> <var>request.method</var> <value>INVITE</value> </equal> </pattern> </servlet-mapping> </servlet-selection> </sip-app>
Można już teraz przystąpić do deployment'u tej aplikacji na serwer SIPowy. W tym celu, należy przejść do zakładki Servers, a następnie z menu kontekstowego wybrać opcję Add and Remove Projects. W sekcji Available Projects zaznaczyć projekt (u mnie: helloSIPServlet) i za pomocą przycisku Add > przenieść go do sekcji Configured Projects. Po tym, należy nacisnąć przycisk Finish.
Może pojawić się następujący komunikat, ostrzegający, że aplikacja zawiera w WEB-INF niestandardowe pliki. To wynika oczywiście z tego, że to sprawdzenie dotyczy aplikacji webowej (Dynamic Web Project), a w WEB-INF jest plik sip.xml. Można spokojnie zignorować to ostrzeżenie, zaznaczyć opcję Don't show me this warning again. i nacisnąć przycisk OK:

Dodanie (i usunięcie) projektu powoduje automatyczną synchronizację, a zatem zakładka Servers powinna wyglądać następująco:

Czas przystąpić do testowania aplikacji "Hello SIP Servlet World" - ale zaraz, w jaki sposób ? W aplikacjach webowych (zwykle) klientem jest przeglądarka internetowa. W aplikacjach SIP (zwykle) klientem jest komunikator SIP (dowolne urządzenie zdolne wysyłać i odbierać komunikaty SIP, czasem pełniące także rolę telefonu, video-telefonu, itp.). Taki komunikator może mieć wiele postaci - fizyczną (i przypominać zwykły telefon stacjonarny, tyle, że podłączony poprzez kabel Ethernet lub WiFi), ale może być również zwykłym oprogramowaniem.
W sieci dostępnych jest wiele darmowych, porządnej jakości komunikatorów SIP do ściągnięcia z sieci. Jednym z lepiej wyposażonych jest X-Lite firmy CounterPath (http://www.counterpath.net/X-Lite-Download.html). Do ściągnięcia ok. 8.5MB.
Instalacja X-Lite
Po uruchomieniu pliku instalacyjnego, pokaże się ekran powitalny - należy nacisnąć przycisk Next:

Następnie zaakceptować warunki licencyjne:

Wybrać folder instalacyjny:

Wybrać miejsce utworzenia skrótów:

Po kilku sekundach, pojawi się ekran informujący o poprawnym zakończeniu instalacji komunikatora:

Przy pierwszym uruchomieniu telefonu, należy skonfigurować konto SIP (czyli parametry jakich X-Lite będzie używać do tego, aby podłączyć się do proxy SIP - w naszym przypadku rolę tego proxy będzie pełnił serwer aplikacyjny SIP - OCCAS 4.0). Na tym ekranie należy nacisnąć przycisk Add:

Wyświetli się ekran konfiguracji połączenia do serwera.
W sekcji User Details należy podać parametry identyfikujące użytkownika tego komunikatora. Parametry tu podane są praktycznie dowolne, gdyż na tym etapie nie korzystamy z mechanizmów security (w tym logowania się do serwera/aplikacji). Najważniejsze parametry są w sekcji Domain Proxy, która określa dokąd będą wysyłane komunikat tworzone przez komunikator. Należy zatem zaznaczyć opcję proxy i w polu Address podać adres IP i port serwera aplikacyjnego (domyślny port dla SIP to 5060).

Komunikator SIP X-Lite w pełnej krasie:

Nie należy zrażać się komunikatem Registration error: 500. Ten błąd wynika z faktu, że telefon nie mógł zarejestrować się (czyli m.in. podać swojego adresu IP) w serwerze, co wynika z tego, że na razie procedura rejestracji (obsługa komunikatu REGISTER) nie została w naszej przykładowej aplikacji zrealizowana.
Ale komunikator działa. I przykładowa aplikacja także. Aby się o tym przekonać, wystarczy w komunikatorze wpisać dowolny numer telefonu i nacisnąć ENTER. Na przykład wpisując: "Waldek" na konsoli serwera powinien zostać wyświetlony komunikat:

W X-lite przełączanie między wprowadzaniem cyfr a liter odbywa się za pomocą SPACJI.
Najnowsze komentarze
18 hours 53 min ago
1 dzień 15 hours ago
6 weeks 3 days ago
9 weeks 6 days ago
12 weeks 5 days ago
13 weeks 3 days ago
14 weeks 22 hours ago
15 weeks 1 dzień ago
15 weeks 2 days ago
15 weeks 2 days ago