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

wtorek, 27 stycznia 2009

Unable to find valid certification path to requested target

--------------------------

Unable to find valid certification path in English

--------------------------

Jeśli nawiązujecie połączenie z usługą sieciową (web service) poprzez https (czyli z użyciem SSL) natrafić możecie na dość znany wyjątek:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target


Oznacza to tyle, że łączymy się z usługą przez SSL i nie znamy lub nie akceptujemy certyfikatu uwierzytelniającego tej usługi. Gdybyśmy łączyli się ze stroną www przez przeglądarkę, wyskoczyłoby nam znane okienko informujące nas, że połączenie nie może być nawiązane, gdyż (cytując Firefox'a) "certyfikat nie jest zaufany, ponieważ certyfikat wystawcy nie jest zaufany.". Wtedy najczęściej klikamy "Zaufaj witrynie" lub "Potwierdź wyjątek bezpieczeństwa" i już możemy oglądać naszą witrynę w bezpiecznym połączeniu SSL.

W przypadku programów napisanych w języku Java, nie mamy pewności, że zawsze po drugiej stronie aplikacji będzie siedział użytkownik, który kliknie "Potwierdź wyjątek bezpieczeństwa". Dlatego, aby aplikacja łączyła się zawsze poprawnie przez SSL, należy wcześniej ten "wyjątek" potwierdzić.
Najprostszym sposobem jest wygenerowanie tak zwanego keystore'a dla danego certyfikatu i potem użycie go w aplikacji. Robi się to w sposób następujący:

1. wygenerowanie pliku .cer

Jest to plik reprezentujący certyfikat. Często jest udostępniany przez firmę, z której serwerem łączymy się przez SSL. Jeśli jednak nie mamy do niego dostępu najprościej go zdobyć wchodząc na dany adres usługi (ten adres uslugi, z która później ma łączyć się nasza aplikacja) poprzez dowolną przeglądarkę. Potwierdzić certyfikat, następnie odnaleźć go w ustawieniach przeglądarki i na końcu wyeksportować do pliku .cer. Większość przeglądarek (na pewno Firefox i Opera) udostępniają taką funkcjonalność.

2. wygenerować keystore

Keystore możemy wygenerować wraz z narzędziem keytool, które dostępne mamy zawsze wraz z naszym JDK. Wywołujemy ten program w konsoli w sposób następujący:

keytool -import -trustcacerts -keystore cacerts -storepass twoje_haslo -noprompt -file cert.cer

gdzie: -file to wygenerowany w punkcie pierwszym plik .cer, -keystore to nazwa pliku keystore (może być dowolna), -storepass to hasło które będzie używane wraz z danym keystorem.

3. ustawienie propertiesów

Na końcu należy wygenerowany plik keystore (w naszym przypadku nazywa się cacerts) wrzucić do katalogu naszej aplikacji, a w samym kodzie ustawić dwa dodatkowe propertiesy:


System.setProperty("javax.net.ssl.trustStore", "cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "twoje_haslo");


Od tego momentu powinniśmy bez problemów łączyć się z dowolną bramką webservicową (czy też jakąkolwiek usługą w sieci) poprzez SSL.

Referencje:
http://wso2.org/forum/thread/3018
http://blogs.sun.com/andreas/entry/no_more_unable_to_find

środa, 21 stycznia 2009

Oracle Application Server (Apex) nie wstaje

Instalując Oracla na Ubuntu natknąłem się na ciekawą sytuację. Instancja bazy była uruchomiona, jednakże nie mogłem połączyć się z Application Serverem (a konkretnie z aplikacja apex, zarządzającą bazą danych). Ponieważ podobną sytuację spotkałem na dwóch różnych kompach, pomyślałęm, że podziele się wiedzą jak wyjść z takiego impasu.

Ponieważ żadnym Oraclowym ekspertem nie jestem, zrobiłem to co wydawało się intuicyjne:

1. sprawdziłem status

pawel@ingrid:~$ sudo /etc/init.d/oracle-xe status
[sudo] password for pawel:

LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 03-NOV-2008 19:35:13

Copyright (c) 1991, 2005, Oracle. All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_XE)))
TNS-12541: TNS:no listener
TNS-12560: TNS:protocol adapter error
TNS-00511: No listener
Linux Error: 111: Connection refused
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ingrid)(PORT=1521)))
TNS-12541: TNS:no listener
TNS-12560: TNS:protocol adapter error
TNS-00511: No listener
Linux Error: 111: Connection refused


2. Zrestartowałem

pawel@ingrid:~$ sudo /etc/init.d/oracle-xe restart
Shutting down Oracle Database 10g Express Edition Instance.
Stopping Oracle Net Listener.

Starting Oracle Net Listener.
Starting Oracle Database 10g Express Edition Instance.

3. I zaczeło działać :)

pawel@ingrid:~$ sudo /etc/init.d/oracle-xe status

LSNRCTL for Linux: Version 10.2.0.1.0 - Production

Copyright (c) 1991, 2005, Oracle. All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_XE)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 10.2.0.1.0 - Production
Uptime 0 days 0 hr. 0 min. 52 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Default Service XE
Listener Parameter File /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/network/admin/listener.ora
Listener Log File /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/network/log/listener.log
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=ingrid)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=8080))(Presentation=HTTP)(Session=RAW))
Services Summary...
Service "PLSExtProc" has 1 instance(s).
Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
Service "XE" has 1 instance(s).
Instance "XE", status READY, has 1 handler(s) for this service...
Service "XEXDB" has 1 instance(s).
Instance "XE", status READY, has 1 handler(s) for this service...
Service "XE_XPT" has 1 instance(s).
Instance "XE", status READY, has 1 handler(s) for this service...
The command completed successfully


Ot wielka filozofia... Ale działa i to chyba najważniejsze :)

czwartek, 13 listopada 2008

Name clash: has the same erasure but does not override it

Pisząc aplikacje wykorzystujące generyki, możecie natrafić na przedziwny błąd. Wyobraźcie sobie interfejs IDao (z pojedyncza metoda updateStubs(List<T>) oraz klasę, która go implementuje AbstractDao. I nagle kompilator krzyczy:

Name clash: The method updateStubs(List) of type AbstractDao<T> has the same erasure as updateStubs(List) of type IDao but does not override it.


Zaraz zaraz, metoda z klasy ma taką samantykę i erasure jak nadrzędna metoda z interfejsu, ale jej nie nadpisuje? O co chodzi?
Spójrzmy na początek definicji interfejsu:


public interface IDao<T extends IStub> {


a następnie na początek defnicji klasy AbstractDao:


public abstract class AbstractDao<T extends IStub> implements IDao {


Co jest nie tak? Otóż wprawna osoba odrazu zauważy (a nieroztropny [czytaj ja] programista przegapi) fakt, iż przy IDao brakuje odwołania do typu generycznego! Poprawnie powyższa definicja powinna wyglądać następująco:


public abstract class AbstractDao<T extends IStub> implements IDao<T> {


Po tej małej zmianie wszystko powino być już w porządku, a kompilator nie krzyczy, że ma metode w podklasie, ale jej nie nadpisze.

środa, 5 listopada 2008

Maven javaee-api-5

Jeśli dane jest Wam pisać aplikacje JEE5 z użyciem mavena, dość paradoksalnie możecie się spotkać z brakiem w dostępnych repozytoriach pliku javaee-api-5.jar (definiującego API standardu JEE5). Jeśli więc kiedykolwiek dostaniecie informacje od mavena, że nie może za żadne skarby znaleźć API JEE5, polecam zajrzeć tutaj:

https://maven-repository.dev.java.net/nonav/repository/javaee/jars/

W repozytorium java.net jar z API standardu leży sobie grzecznie, czekając, aż go ktoś ściągnie.

wtorek, 4 listopada 2008

Zmiana portu JBoss Application Server z 8080 na inny

JBoss Application Server uruchamia się standardowo na porcie 8080. W odróżnieniu od Glassfisha nie ma admina webowego (co jest zastanawiające czemu) i żeby cokolwiek zmienić w konfiguracji, trzeba poedytować pliki konfigów.

W tym poście zakładam, że JBoss zainstalowany jest w katalogu /opt/jboss/. Aby zmienić port HTTP z 8080 na jakiś inny należy dostać się do pliku server.xml zlokalizownego w /opt/jboss/server/default/deploy/jboss-web.deployer/ i wyedtować go. Odnajdujem poniższy wpis i w miejscu XXX wpisujemy intersujący nas port (na przykład 80):


<Connector port="XXX" address="${jboss.bind.address}"
maxThreads="250" maxHttpHeaderSize="8192"
emptySessionPath="true" protocol="HTTP/1.1"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />

poniedziałek, 3 listopada 2008

Oracle Apex widoczny poza localhost'em

Ostatnio pisałem jak zainstalować Oracla na Ubuntu, dziś pora przyjrzeć się aplikacji webowej Apex (pozwalająca zarządzać bazą danych), która standardowo instaluje się wraz z Oraclem i dostępna jest pod adresem http://localhost:8080/apex. Wszystko działa fajnie, do czasu gdy chcielibyśmy dostać się do aplikacji przez inny adres niż http://localhost, czyli zdalnie. Poniżej krótka instrukcja jak to zrobić:

1. zainstaluj sqlplus jeśli (jeszcze nie masz):

apt-get install sqlplus

2. ustaw ORACLE_HOME (jesli jeszcze tego nie zrobiles):

ORACLE_HOME=/usr/lib/oracle/xe/app/oracle/product/10.2.0/server

3. zaloguj się do sqlplusa jako user SYSTEM

sqlplus system

4. gdy pojawi się sql prompt (ktoś zna polski odpowiednik słówka prompt?) wpisz:

SQL> EXEC DBMS_XDB.SETLISTENERLOCALACCESS(FALSE);


Powinno zacząć działać.

poniedziałek, 25 sierpnia 2008

java.util.Date vs java.sql.Date

Natknąłem się na ciekawe rozwiązanie architektoniczne w JDBC: obiekt java.sql.Date. Jest to obiekt, który dziedziczy bezpośrednio po java.util.Date, pozwalający nam mapować w naszych beanch pola typu Date z naszych baz danych.
Czy wszystko jest takie piekne? Nie do końca, gdyż w naszych beanach zwykle trzymamy obiekty typu java.util.Date.
Wyboraźmy sobie prosty przykład:

Mamy klase User w postaci

public class User
{
protected String userName;
protected Date birthDate; // tutaj java.util.Date czyli standard

//odpowiednie gettery i settery
}
Posiadamy również odpowiadającą jej tabelę w bazie danych:

CREATE TABLE Users (
userName VARCHAR2(150),
birthDate DATE );

Sytuacja jak najbardziej standardowa. Teraz jeśli wyciągnięte dane z bazy (przy pomocy ResultSeta) dodamy do naszego beana:

User u = new User();
u.setUserName(rSet.getString(1));
u.setBirthDate(rSet.getDate(2));

nic się nie stanie. W prawdzie metoda User.setBirthDate oczekuję java.util.Date, a ResultSet.getDate zwraca java.sql.Date, to jednak wszystko jest w porządku, gdyż java.sql.Date dziedziczy po java.util.Date. Jaja zaczynają się, gdy informacje chcemy ponownie przekazać do bazy danych.
Teraz gdy updateujemy jakies informacje przy pomocy jakies procedury skladowanej czy poprzez wywolanie SQL'owego UPDATE, zawsze ale to zawsze poprosza nas o Date w postaci java.sql.Date. Czyli kod
statement.setDate(2,user.getBirthDate());
sie po prostu nie skompiluje. Rzutowanie nic tu nie da, gdyż przykładowo poniższy kod:
user.setBirthDate(new Date());
statement.setDate(2,(java.sql.Date)user.getBirthDate()); // tu exception
się poprostu wywali przy pierwszym wywołaniu. Trzeba utworzyć explicite obiekt java.sql.Date, ale żeby nie było za prosto, nie ma żadnego konstruktora typu public Date(java.util.Date utilDate). Nie, przecież to by było zbyt proste. Zamiast tego musimy zrobic new java.sql.Date(utilDate.getTime()). Konstruktor java.sql.Date przyjmuje longa jako liczbę milisekund od roku 1970, a metoda getTime z java.util.Date taka informacje zwraca. Wszystko działa okej, ale czy na pewno to jest dobre rozwiązanie? Szczerze mówiąc, ja nie wiem. Skoro sami ludzie z Sun Microsystems mówią, że java.sql.Date to tylko "thin wrapper", to po co w ogóle został wprowadzony? Czy istnieje jakiś lepszy (w sensie nie polegający na roku 1970) sposób na konwertowanie dat z java.util na java.sql? Googlałem pobieżnie, nie znalazłem. Może ktoś zna?