18 Kasım 2013 Pazartesi

DateTime'ı String Olarak Okuma ve Yazma İşlemleri

Not : DateTime İşlemleri başlıklı yazıya göz atabilirsiniz.

ISO 8601 formatında yazma

Joda
Joda zaten ISO 8601 formatında çalışmak üzere tasarlandığı için bu işlem çok kolay.
DateTimeFormatter sınıfını yaratan 3 tane factory sınıftan birisi olan ISODateTimeFormat sınıfını kullanmak yeterli.


//Çıktı olarak : bugünün tarihi olan 2012-05-08T08:48:02.332+03:00 alırız

DateTime dt = new DateTime();
DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
String str = fmt.print(dt);
Eğer istenirse DateTimeFormatter DateTime sınıfının toString() metoduna da geçilebiliyor. Örnek:
DateTimeFormatter formatter = DateTimeFormat.forPattern("MM/dd/yyyy");
DateTime dateTime = new DateTime();
dateTime.toString(formatter);
Boost
to_iso_extended_string veya to_iso_string() metodları ile verilen nesne stringe çevirilebilir.
//Çıktı olarak 2011-08-02 alırız.


Belirsiz bir formatta yazma

Joda
String dateFormat = ("MM/dd/yyyy");
DateTime date;
String formattedDate = DateTimeFormat.forPattern(dateFormat).print(date);
Aşağıda DateTimeFormat sınıfının kullanım ile ilgili daha detaylı bilgi var.

SQL
Oracle Date veri tipini kendi bildiği bir yapıda saklıyor.
 Bu yapıyı istediğimiz bir şekle çevirmek için TO_CHAR metodunu kullanırız. Örnek:


-------------------------------------OKUMA İŞLEMLERİ-----------------------------------------------
ISO 8601 formatında okuma
ISO8601 tarihleri standartlaştırıyor. Aşağıdaki şekilde görülebilir.

ISO8601 basic ve extended format olarak kullanılabiliyor. Basic formatta arada hiç ayraç yokken, extended formatta tarih alanları arasında "-" , zaman alanları arasında ise ":" işareti kullanılıyor. Saniyeden ile milisaniye arasında ise "." ayracı var. Tarih ve zaman alanları arasındaki T işareti ise opsiyonel.

Bu standart ile 3 türlü gösterim şekli var. Bildiğimiz takvim gösterimi, Yılın kaçıncı günü gösterimi (Ordinal), Yılın kaçıncı haftası gösterimi (Week). Aşağıdaki şekildeki tarihlerin hepsi aynı zamanı gösteriyor.

Boost
date
Date sınıfının from_simple_string metodu ISO8601 formatında günleri okuyabiliyor. Örnek:

ptime
Boost ile gelen from_iso_string() metodu ile delimeter kullanmayan stringleri okuyup tekrar zamana çevirebilme imkanı var.
//Çıktı olarak 2012-Sep-27 06:23:39 verir 
std::cout << boost::posix_time::from_iso_string("20120927T062339");
time_from_string metodu ile de delimeter kullanan stringi okuma imkanı var. Örnek:


iso_extended_string formatında okuma işlemini ise buradan aldım. boost'un time_input_facet sınıfının set_iso_extended_format metodu ile belirtilen formatta okuma yapılabiliyor.

Joda

Eğer timezone UTC ise aşağıdaki gibi parse edebiliriz.

DateTimeFormatter formatter = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC);
DateTime datetime = formatter.parseDateTime(dateAsString); 


Bir başka örnekte ise 
DateTime.parse("2012-08-16T07:22:05Z") //UTC saat dilimindeki ISO8601 saat örneği

yukarıdaki ile aynı işlemi yapar.


Yalnız yukarıdaki örneklerde verilen saat kendi saat dilimimize göre çevirilir.
Eğer çevirilme yapılmasın isteniyorsa aşağıdaki gibi yapılabilir.
val date1 = formatter.withOffsetParsed().parseDateTime("2012-01-03T00:00:00Z");
veya
val formatter = ISODateTimeFormat.dateTimeNoMillis
val date1 = formatter.withZone(DateTimeZone.UTC).parseDateTime("2012-01-03T00:00:00Z")
Eğer parse işlemi başarısız olursa IllegalArgumentException atılır.

ISO 8601'in başka formatları da vardır. Örneğin ISO week date (xxxx-'W'ww-e yani  2006-W52-7) veya sadece date (yyyy-MM-dd yani 1981-04-05) gibi. Bu tür stringleri parse etmek için aşağıdaki örnek kullanılabilir.


Belirsiz bir formatta okuma
boost
boost ile gelen boost::gregorian::date_input_facet ve boost::posix_time::time_input_facet sınıflarını kullanarak  date veya datetime okuma imkanı var.

Örnek:
boost'un time_input_facet sınıfı ile belirtilen formatta okuma yapılabiliyor.
Bir başka örnek:
  

Örneği buradan aldım.
 
Java
Formatlama işleme için kullanılan parametrelerin görevleri aşağıdaki gibi.

Gün İçin
dd : Ayın kaçıncı günü olduğunu okur örneğin 08-AUG-12 12.00.00 AM için dd 08 kısmını okumak için kullanılır.
DD : Yılın kaçıncı günü olduğunu okur

EEE :  Günün harf olarak kısaltılmış halini okur. Örneğin İngilizce locale kullanılıyorsa "Sun" gibi
Ay için
MMM : Ayın harf olarak kısaltılmış halini okur. Örneğin İngilizce locale kullanılıyorsa "Dec" gibi
MM : Ayın rakam olarak girilmiş halini okur
Yıl İçin
yyyy : Yılı okur
yy :  Yılı 19xx olarak okur. 12 rakamı için 2012 yerine 1912'yı bulur. Kullanılmasını tavsiye etmem.
Saat İçin
hh : AM/PM formatında saati okur. Saat değeri 1-12 arasındadır.
HH : 24 saat formatında saati okur. Saat değeri 0-23 arasındadır.
aa : AM/PM kısmını okur
Dakika İçin
mm : Dakikayı okur
Saniye İçin
ss : Saniyeyi okur
Milisaniye İçin
SSS: Milisaniyeyi okur
Saat Dilimi İçin
z : Saat dilimi kısmını okur. Saat dilimlerine isim verilir.
Z : RFC 822 formatında saat dilimi. Bu formatta saat dilimi -0700 şeklinde gösterilir.

Java ile SimpleDateFormat sınıfı bu işi hallediyor.

DateFormat dateFormat = new SimpleDateFormat("E M d HH:mm:ss z yyyy");
Date date = dateFormat.parse("Thu Jun 07 13:01:59 IST 2007");
Bir başka örnekte eğer istenirse kullanılan tarih deseni applyPattern() metodu ile değiştirilebiliyor.
Apache Commons
DateUtils sınıfının parseDate veya parseDateStrictly metodları kullanılarak, formatını hiç bilmediğimiz bir stringi bir format dizisi vererek, okumak mümkün.

Joda ve DateTimeFormat.forPattern
Aşağıdaki örnek ISO 8601 ile aynı olmasına rağmen elle parse ediliyor.
String date = "2010-10-03T16:58:07.000+02:00";
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
DateTime dateTime = formatter.parseDateTime(date);
Burada dikkat edilmesi gereken nokta DateTimeFormat sınıfına "dd.MM.yyyy" verilse bile yıl alanına 4 haneli yıl yerine iki haneli yıl girilse bile doğru parse ediyor. Örneği yıla 12 girilirse yılı 2012 yerine direk olan M.S. 12 gibi algılıyor.

Bir başka örnek ise
String date = "Sun, 20 May 2012 01:07:11 +0000";
DateTimeFormatter formatter = DateTimeFormat.forPattern("EEE, dd MMM YYYY HH:mm:ss Z");
DateTime dateTime = formatter.parseDateTime(date);

Joda ve DateTimeFormatter.patternForStyle
Buradaki soruda anlatıldığı gibi patternForStyle metodu ile  locale'e göre Short,Medium,Long,Full deseni bulunabilir.

Joda ve DateTimeFormatter.withOffsetParsed
DateTimeFormatter.parseDateTime() metodu verilen string'i yerel saat dilimine çevirir. Ancak çevirmesin istiyorsak withOffsetParsed() ile kullanabiliriz. Örnek:
DateTimeFormatter dfOne = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss 'GMT'Z yyyy");

//Yerel saate çevirir
//Mon Mar 16 04:10:40 GMT+0530 2009
DateTime dateTime1 = dfOne.parseDateTime("Mon Mar 16 8:40:40 GMT+1000 2009");

//Yerel saate çevirmez
//Mon Mar 16 08:40:40 GMT+1000 2009
DateTime dateTime3 = dfOne.withOffsetParsed().parseDateTime("Mon Mar 16 8:40:40 GMT+1000 2009");

 
Joda ve DateTimeFormatterBuilder
Android using Joda time to calculate diference between dates başlıklı soruda DateTimeFormatterBuilder kullanımına bir örnek var.

 Bir başka örnek ise
QT
QDate fixDate = QDate::fromString ("27092012", "ddMMyyyy");
C#
DateTime.ParseExact ile istenilen formatta okuma yapılabilir. Örnek:
DateTime date = DateTime.ParseExact(txtDate.Text, "dd-MM-yyyy HH:mm:ss", CultureInfo.InvariantCulture); 
Bir başka örnekte ise
DateTime a = DateTime.ParseExact("2013-Jan-31", "yyyy-MMM-dd", CultureInfo.InvariantCulture);
DateTime.TryParseExact metodu ise birden çok formatta okuma işlemini yapabilmeyi sağlar.

DateTime sınıfı da aynı QT'deki gibi Date ve Time olarak ayrı ayrı property'lere ayrılabilir.



16 Kasım 2013 Cumartesi

JAX-WS (Java API for XML Web Services)

Aşağıda JAX-WS ile ilgili aldığım notlar var.

JAX-WS Anotasyonları
Bu konuyla ilgili olarak JAX-WS annotations başlıklı yazıya göz atmak faydalı. Yazıda geçen JSR 181 ile ilgili bilgi ise aşağıda. Daha yeni olan JSR 224 ile ilgili bilgi ise burada.

Servis ne Anlama Geliyor?
Servis programlama dünyasında bir çok farklı anlama gelir. Örneğin çok katmanlı mimarilerde, kullanıcı arayüzü ve veritabanı arasındaki, iş mantığını içeren kod parçası anlamına gelir. Bu tür yapılarda servisler veritabanına yapılan transaction'ı da kontrol ederler.

SOAP çağrılarında ise servis fiziksel bir uç nokta ve API'ler gibi düşünülmeli. Aşağıda bu API'lerin nasıl çalıştığı ve dışarıya nasıl açıldıkları ile ilgili bilgiler var.

JSR 181
JAX-WS ile JSR 181 ile kullanılması kararlaştırılan anotasyonlar kullanılıyor. Bu anotasyonlardan bazıları
@WebService, @WebMethod, @WebParam vs. Anotasyonlar javax.jws paketinde mevcut.


javax.jws.WebService ve serviceName

Eğer bir web servisine aşağıdaki gibi isim verilirse 
@WebService(name = "myService")
üretilen wsdl dosyasında aşağıdaki gibi bir XML üretiliyor

<service name="myService">
    <port name="myServicePort" binding="tns:myServicePortBinding">
    <soap:address location="http://localhost:8080/myApp/webservice"/>
    </port>
</service>
Burada kullanılan servis ismine ?wsdl eklenip sorgulama yapılırsa XML çıktısı görülebilir.

Bazen wsdl dosyasında wsdl: şeklinde kullanım da görülebilir. O zaman XML aşağıdaki gibi olacaktı.

<wsdl:service name="myService">
    <wsdl:port name="myServicePort" binding="tns:myServicePortBinding">
    <soap:address location="http://localhost:8080/myApp/webservice"/>
    </wsdl:port>
</wsdl:service>
Eğer serviceName atanmazsa, JAX-WS sınıfın ismine "Service" kelimesini ekliyor. Örnek:
Bu sınıf için wsdl dosyasını adresi aşağıdaki gibidir.Sınıfın ismine yapılan ektentiye dikkat.
http://localhost:9080/service/ServiceImplService?wsdl
javax.jws.WebService ve portName
Eğer WebService'e portName vererek aynı arayüzden türeyen ancak farklı çalışan sınıflar yazabiliriz. Örnek:
Üretilen wsdl aşağıdaki gibi olacaktır.

javax.jws.WebMethod

Eğer bir metodun dışarıya açılmasını istemiyorsak aşağıdaki gibi yapıyoruz.
@WebMethod(exclude = true)
javax.jws.OneWay

Eğer bir metodun geriye döneceği bir cevap yoksa onu OneWay olarak işaretlersek WSDL dosyasında port'a bağlı olan output tagleri üretilmez. Örnek:
@WebMethod
@OneWay
public void myCall ()...
javax.jws.soap.SOAPBinding

@WebService
@SOAPBinding(style = Style.DOCUMENT)
public interface HelloWorld{
}

JAX-WS document/literal tarzı çalıştığı için başka bir örnek te belki doğru olmazdı zaten.

JAX-WS RI ve WS-Addressing
WS-Addressing'in açıklayan gördüğüm en iyi yazı  What is WS-Addressing. Bu standart ile mesajın kimliği ve get/post aksiyonlarından hangisinin yapılmak istendiği Http protokolü yerine SOAP mesajının içine konuluyor.

JAX-WS RI ve WS-ReliableMessaging
Desteklemiyor
  
JAX-WS RI ve WS-Security
Desteklemiyor. WS-Security SSL anlamına gelmiyor. Eğer web servis noktadan noktaya çağrı şeklinde ise transport seviyesinde SSL kullanmak güvenliği sağlamak için yeterli ancak servis ara bağlantı sistemler tarafından iletiliyorsa her yere SSL kurmak yerine mesajların güvenliğini sağlamak için  WS-Security kullanılıyor. Bu standart ile web servis çağrısına security token yerleştirmek mümkün. Aşağıdaki örnekte WS-Security desteklenmese bile UsernameToken yerleştirme örneği var. SOAPHandler'dan türeyen bir sınıf aracılığıyla iş başarılıyor.
 
API arayüzü
Çoğu Java standardında olduğu gibi JAX-WS için de bir API arayüzü bir de reference implementation bulunuyor. Sun tarafından sağlanan jaxws-rt.jar (JAX-WS Implementation Package), JDK ile gelmiyor. Bu dosyayı Maven ile projeye dahil edince aşağıdakine benzer bir hiyerarşi oluşuyor.


Bu hiyerarşide jaxb-impl.jar dosyası Java Architecture for XML Binding standardını gerçekleştiren kütüphane. Bu kütüphane aracılığıyla Java sınıfları XML'e dönüştürülebiliyor.

SAAJ (SOAP with Attachments API for Java) Nedir?
saaj-impl.jar dosyası ise SOAP with Attachments API for Java standardını gerçekleştiren kütüphane. Bu kütüphane aracılığıyla binary SOAP mesajları eklenti olarak gönderilebiliyor. JAX-WS daha üst seviye bir API ancak altta SOAP mesajı oluşturmak için SAAJ kullanıyor.

SAAJ örneklerinde Factory sınıflarının da newInstance() metodu ile yaratıldığı görülebilir. Böylece sağlayıcılar (vendor) kendi gerçekleştirimlerini sunabilirler. Factory sınıfı system property'lerini okuyarak (örneğin javax.xml.soap.MessageFactory gibi ) gerçek gerçekleştirimi sınıfını bulur.

javax.xml.soap.SOAPConnectionFactory sınıfı
Örnek:
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage message = messageFactory.createMessage();
//Populate message
// Send SOAP Message to SOAP Server
String url = "http://mycompany.com/test.asmx";
SOAPMessage soapResponse = soapConnection.call(message);

Diğer Kütüphaneler?
JAX-WS bir standart olduğu için bu standardı gerçekleştiren diğer kütüphaneler de mevcut. Bunlardan bazıları JAX-WS-Refrence Implementation, JBossWS, CFX, METRO, AXIS2 sayılabilir. Neden diğer kütüphanelere gerek duyuluyor ? JDK ile gelen RI sadece WS-Addressing'i destekliyor. Eğer diğer standartları da kullanmak istiyorsak başka bir kütüphane seçmemiz lazım.

Contract Last ne demek?
Java: JAX-WS Mapping sorusunda da anlatıldığı gibi contract last Java kodundan XSD dosyasının üretilmesi anlamına geliyor.

What happens to generic class in jax-ws webservice? sorusunda web-servisi yazarken uyulması iyi olan kurallar bulunabilir.

JAX-WS 2.0/2.1 uyumlu olmak
What does JAX WS 2.0/2.1 compliant means? sorusunda da cevaplandığı gibi JAX-WS'nin WSDL dosyasından kendi kendine bir POJO modeli oluşturabilmesi anlamına geliyor.

JAX-WS ve WSServlet
JAX-WS de bir çok diğer çatı gibi servlet teknolojisi kullanıyor.WSServlet JAX-WS tarafıdan kullanılan dispatcher servlet. Aşağıda WSServlet'ı tanımlama örneği var.
<listener>
    <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
    <servlet-name>TempConvertWS</servlet-name>
    <servlet-class>com.sun.xml.ws.transport.http.WSServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>TempConvertWS</servlet-name>
    <url-pattern>/tc</url-pattern>
</servlet-mapping>


JAX-WS ve WebServiceContext 
Her web servis çağrısı bir servlet içinde işlenir. javax.xml.ws.WebServiceContext sınıfı servlet ve çağrı ile ilgili bilgilere erişebilmemizi sağlar.
Örnek:

JAX-WS ve WSServletContextListener
Bu konuyu daha sonra yazacağım.

JAX-WS ve Spring Servlet

JAX-WS ve Spring'i birleştirmenin 3 tane yolu var. Her yöntemi ve aralarındaki farkları JAX–WS with Spring and Maven Tutorial yazısında görebilirsiniz.

WSSpringServlet Yöntemi
Bu yöntem Java EE platformlarına uygun değilmiş. Sebebini tam bilmiyorum ancak Tomcat gibi platformlara uygunmuş. Bu yöntemde WebServis sınıfımızın hayat döngüsü Spring tarafından yönetiliyor.

jaxws-spring projesini Maven ile projeye dahil edince JAX-WS ve Spring beraber çalışabilir hale geliyorlar ve aşağıdakine benzer bir hiyerarşi oluşuyor.

JAX-WS projelerinde normalde dispatcher servlet olarak jaxws-rt-2.2.6-2.jar dosyasında bulunan com.sun.xml.ws.transport.http.servlet.WSServlet sınıfı kullanılıyor. 
What is com.sun.xml.ws.transport.http.servlet.WSServlet and any documentation on this. sorusu bu servlet hakkında biraz daha bilgi veriyor. Ancak Spring ile entegre olabilmek için jaxws-spring-1.8.jar dosyasında bulunan com.sun.xml.ws.transport.http.servlet.WSSpringServlet sınıfı kullanılmalı.

Aslında her iki sınıf ta gelen istekleri WSServletDelegate sınıfına yolluyorlar.

SimpleJaxWsServiceExporter Yöntemi
Spring ile gelen bir diğer sınıf olan SimpleJaxWsServiceExporter JAX-WS ile gelen gömülü Http Server'ı kullanarak web servisleri de çalıştırabiliyor. Bu sınıfı kullanmaya hiç ihtiyaç duymadım ama konsol tipi uygulamalarda işe yarayacağını tahmin ediyorum. Aşağıda kod örnekleri var.
Bu sınıf aşağıdaki örnekte olduğu gibi @Service ve @WebService ile işaretli kodu web servis olarak dışarıya açmamızı sağlıyor.



JAX-WS ve javax.xml.ws.handler.MessageContext Arayüzü
MessageContext arayüzü ile SOAP mesajında olmayan ancak transport protokolü içinde bulunan meta-data'ya erişmek mümkün. A little bit about Message Context in JAX-WS başlıklı yazı bu konuda bilgilendirici.
HttpServletRequest aracılığıyla HttpSession'a erişmek
http://sirinsevinc.wordpress.com/category/jaxws/ adresinde WebServis sınıfı içinden ServletRequest sınıfına erişmek için kod örneği var. Aşağıdaki örnekte MessageContext ve MessageContext.SERVLET_REQUEST beraber kullanılıyor.
HttpServletRequest aracılığıyla Client IP'sine erişmek
jax ws getting client ip sorusunda örnek var.
Eğer gömülü bir Http sunucusu kullanılıyorsa, servlet ortamı olmayacaktır. O zaman da aşağıdaki kodu kullanmak gerekir.

Spring XML Tanımlamaları
Web servisini spring tarafından yönetilen bir bean haline getirmek için aşağıdakine benzer bir tanımlama yapmak lazım.
<wss:binding url="/webservice">
    <wss:service>
        <ws:service bean="#mybean"/>
    </wss:service>
</wss:binding>
Ancak wss namespace'ini tanıtmak bir problemli çünkü Spring and Jax-WS : where are xsd schema?  sorusunda da söylendiği gibi jax-ws.dev.java.net sitesindeki url tanımları değişmiş ve internetteki örnekleri kullanınca SAXParseException alınabiliyor. Örneğin internetteki örnekte

http://jax-ws.java.net/spring/core http://jax-ws.java.net/spring/core.xsd
http://jax-ws.java.net/spring/servlet http://jax-ws.java.net/spring/servlet.xsd

şeklinde kullanılmış. Ancak benim sistemimde

http://jax-ws.dev.java.net/spring/core spring-jax-ws-core.xsd      
http://jax-ws.dev.java.net/spring/servlet spring-jax-ws-servlet.xsd

şeklinde kullanmak gerekti.

Doğru url'yi bulmak için jaxws-spring-1.8.jar dosyası altındaki META-INF/spring.schemas dosyasındaki url'leri kullanmak problemi çözüyor.

SOAP mesajları
Konu için SOAP Anatomisi başlıklı yazıya bakılabilir.

JAXB
JAXB yazısına taşıdım.

WSDL ve XSD
WSDL (Web Services Description Language) web servislerinin sunduğu arayüzlerin tanımlanabilmesi için kullanılan XML tabanlı tanımlama dilidir.

Yazılan servisin wsdl ve xsd dosyalarını görmek için
http://localhost:8080/MyApp/webservice?wsdl ve http://localhost:8080/MyApp/webservice?xsd=1 adreslerine bağlanmak yeterli.

wsimport kullanmadan dynamic proxy yöntemi ile client yaratmak
Aşağıdakine benzer bir kod ile dynamic proxy yaratarak herhangi bir webservisini kullanmak mümkün.
URL url = null;
try {
    url = new URL("http://localhost:8080/MyApp/webservice?wsdl");
} catch (MalformedURLException e1) {
    e1.printStackTrace();
}
QName qname = new QName("http://webservice.mycompany.com.tr/", "SorgulaWsService");

Service service = Service.create(url, qname);

ISorgulaWs sorgulaws = service.getPort(ISorgulaWs.class);
sorgulaws.getUcret();
Burada dikkat edilmesi gereken husus JAXWS client erroring out when calling a stateless session bean exposed as a webservice sorusunda da açıklandığı gibi WebServisimizin bir interface kullanarak yazılması.

Bir başka örnek ise aşağıda.

QName serviceName = new QName(Namespace.SERVICE, "FileService");
service = new FileService(new URL("http://localhost:8059/WS/FileService?wsdl"), serviceName);
file_service = service.getSOAP11();


Bu yöntemin dezavantajı her çağrı için karşıdan wsdl dosyasının istenmesi. How to cache JAX-WS stub/port in Java? sorusuna verilen cevapta bir çözüm sunulmuş.

wsimport
WSDL dosyasından java sınıfları üretmek için wsimport komutunu kullanmak lazım. wsimport komutu JDK ile geliyor ve bin dizininde kurulu. Örnek:

wsimport.exe http://localhost:8080/MyApp/webservice?wsdl
How to use wsimport when server expects client certificate? sorusunda bir başka örnek var.

-d : seçeneği ile dosyaların yaratılacağı dizin belirtilebiliyor.
-keep : seçeneği ile üretilen dosyalar silinmiyor. Örneği buradan aldım

-p : seçeneği ile üretilecek dosyalarda kullanılacak paket ismi belirtilebiliyor.
-Xnocompile : seçeneği ile üretilen dosyalar derlenmiyor

Eğer hem webservisimiz hem de test kodu aynı projede olacaksa -p ile test kodu için farklı bir paket ismi verilmesi daha uygun olur.
wsgen
Burada yazdığına göre bu komut Java 8 ile kaldırılacak.Bu komut ile wsimport birbirlerine benziyor. Aralarındaki fark wsimport WSDL dosyasından client kodu üretirken wsgen direkt SEI'den (Service Endpoint Implementation yani Java kodu) client kodu üretiyor.
-cp : seçeneği ile classpath olarak kullanılacak dizin veriyor. SEI kodunun belirtilen cp altında olması lazım.
-keep : Yukarıdaki ile aynı
-s : seçeneği ile üretilecek kodun konulacağı dizin veriliyor.
Örnek :

wsdl2java
Bu komut ta Apache CFX ile geliyor ve wsimport gibi wsdl dosyasından java kodu üretmeye yarıyor.

Güvenlik
JAX-WS Password Type PasswordText sorusunda WebServis güvenliği ve HTTP güvenliği arasındaki farktan bahsediliyor.

Maven
jaxws-rt kütüphanesini projeye eklemek için aşağıdaki gibi tanımlama yapmak yeterli.
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>2.2.6-2</version>
</dependency>
Ancak eğer jBoss gibi bir  sunucu kullanıyorsak Tomcat'in tersine bu sunucular jaxws-rt ile yüklü geliyorlar. O zaman scope=provided yapılmalı.

Which is the best maven's plugin to generate a Web Service Client? sorusuna göz atmakta fayda var.

Bazı JAX-WS sınıfları
SOAPHandler
Bu konu ile ilgili A little bit about Handlers in JAX-WS sorusuna bakılabilir.Bir handler'ı tanıtmak için örnekteki gibi @HandlerChain (file = "soaphandlerchain.xml") anotasyonu ile tanıtılabilir.

SOAPPart'a erişmek için aşağıdaki kod kullanılabilir.Aşağıda SOAP mesajının yapısı var.

@Override
public boolean handleMessage(SOAPMessageContext messageContext) {
    SOAPMessage msg = messageContext.getMessage ();
    SOAPPart sp = msg.getSOAPPart ();
    SOAPEnvelope env = sp.getEnvelope ();
}

javax.xml.ws.BindingProvider
Bu sınıf ile servisi çağırırken kullanılacak bazı parametreleri atamak mümkün. Genel kullanım şekli aşağıdaki gibi.

ENDPOINT_ADDRESS_PROPERTY
Bu alan ile çağrılacak URL'yi atamak mümkün.
HTTP_REQUEST_HEADERS
Bu alan ile kullanılacak encoding'i atamak mümkün.
Map<String, Object> reqContext = ((BindingProvider) service).getRequestContext();
Map httpHeaders = new HashMap();
httpHeaders.put("Content-type",Collections.singletonList("text/xml;charset=ISO-8859-1"));
reqContext.put(MessageContext.HTTP_REQUEST_HEADERS, httpHeaders);
USERNAME_PROPERTY ve PASSWORD_PROPERTY
Bu alanlar ile Basic Http Authentication yapmak mümkün. Örnek:

CONNECT_TIMEOUT ve REQUEST_TIMEOUT
Bağlanma ve istekte zaman aşımı verebilmek mümkün. Örnek:

MyInterface myInterface = new MyInterfaceService().getMyInterfaceSOAP();
Map<String, Object> requestContext = ((BindingProvider)myInterface).getRequestContext();
requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, 3000); // Timeout in millis
requestContext.put(BindingProviderProperties.CONNECT_TIMEOUT, 1000); // Timeout in millis
myInterface.callMyRemoteMethodWith(myParameter);

SSLSocketfactory
Bu alan ile servisi çağırırken kullanılacak SSL ayarlarını atamak mümkün

BindingProvider bindingProvider = (BindingProvider) service;
bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", getCustomSocketFactory());

Aşağıda ise sınıf hiyeraşisi var.
javax.xml.ws.EndPoint
publish metodu
Bu metod ile JVM içinde gömülü bulunan bir sunucu çalıştırılıyor. Örneği burada görmek mümkün.

WSBindingProvider
Bu sınıf sadece JAX-WS RI tarafından sağlanıyor. Aşağıdaki örnekte bu sınıf aracılığıyla bazı header parametrelerini atama örneği mevcut.


22 Ekim 2013 Salı

Swing Notlarım

AbstractTableModel

public int getRowCount {
  return list.size();
}

public int getColumnCount(){
  return columnNames.length();
}

DefaultTableCellRenderer
public Component getTableCellRendererComponent() {}

15 Ekim 2013 Salı

Hibernate Connection Pool

Not : Eğer "Using Hibernate built-in connection pool (not for production use!)" şeklinde bir mesaj alırsak sebebi Hibernate ile gelen DriverManagerConnectionProvider sınıfının veritabanı connection pool olarak kullanılmasıdır. Tavsiye edilen buradaki örnekteki gibi C3P0ConnectionProvider sınıfının kullanılmasıdır.

Hibernate ve Connection Pool
Hibernate ile bir çok connection pool kütüphanesi kullanmak mümkün. Bunlar arasında C3P0, Proxool, DBCP sayılabilir. Hibernate ile bu kütüphanelerin hangi arayüz ile birleştirildiğini aşağıdaki şekilde görmek mümkün.

Connection Pooling başlıklı yazıda tüm kütüphanelerin konfigürasyon parametreleri ile ilgili bilgi mevcut. Ayrıca Hibernate: Providing Connections for Hibernate başlıklı yazıya göz atmak faydalı olabilir.

C3P0
C3P0ConnectionProvider bir connection pool sağlayıcısıdır. En önemli özelliklerinden birisi de How to check if connection alive? sorusunda da açıklandığı gibi pasif bekleyen veritabanı bağlantılarını aşağıdaki SQL benzeri bir cümle ile arada bir kontrol etmesidir.
Bu sınıfı kullanmak için aşağıdaki kütüphaneyi projeye eklemek yeterli.
Dikkat edilmesi gereken nokta burada açıklandığı gibi hibernate ayarları için kullanılan konfigürasyon anahtar değerler ile C3P0 ile kullanılan konfigürasyon anahtar değerler farklı.
Aşağıdaki C3P0 içindeki ComboPooledDataSource sınıfını kullanma örneği var.
protected Connection getConnection() throws NamingException, SQLException {
    ComboPooledDataSource cpds = new ComboPooledDataSource();
    try {
        cpds.setDriverClass( "net.sourceforge.jtds.jdbc.Driver" ); //loads the jdbc driver    
        cpds.setJdbcUrl( "jdbc:jtds:sqlserver://10.38.28.77/MyDB" );  
        cpds.setUser("sa");                                 
        cpds.setPassword("password");  
        cpds.setMaxStatements( 180 );
    } catch (PropertyVetoException e) {
        e.printStackTrace();
    }     
    return cpds.getConnection();
 }
DBCP
Apache'nin kütüphanesi. Burada kod içinden kullanma örneği mevcut. Önemli sınıfları şunlar

org.apache.commons.pool.impl.GenericObjectPool
Connection nesnelerini saklayan sınıf

GenericObjectPool connectionPool = new GenericObjectPool();
connectionPool.setMaxActive(10);

GenericObjectPool sınıfının addObject() metodu çağırılarak pool'u önceden doldurmak mümkün.


org.apache.commons.dbcp.DriverManagerConnectionFactory 
Gerektikçe yeni bir connection nesnesi açan factory.


org.apache.commons.dbcp.PoolableConnectionFactory
DriverManagerConnectionFactory ve GenericObjectPool nesnelerini birleştirir.

org.apache.commons.dbcp.PoolingDataSource
 Bilindik DataSource arayüzünü gerçekleştiren sınıf.



10 Ekim 2013 Perşembe

IFF Mode5

IFF
IFF yerdeki bir radarın havadaki uçağı sorgulayıp cevap alması prensibine dayanır. Örnek bir şekili buradan aldım.


Önemli bir not ise son yıllarda "Ters IFF (Reverse IFF)" kavramının ortaya çıkması. Bu çalışma şeklinde hava aracı, yerdeki unsurları sorgular. Böylece bu unsurların dost ateşine maruz kalması engellenebilir.

Sorgulamanın bir kaç modu vardır. Bunlar aşağıda açıklanmıştır.

IFF Sorgu/Cevap Modları ve Açıklamarı

Her IFF sorgulaması farklı bir paternde gönderilir. Her sorgulamada iki tane pulse kullanılır, bunlara da P1 ve P3 denilir. İki pulse arasındaki zaman farkı sorgu türünü belirler. Paternler arasındaki farkları gösteren şekli buradan aldım. Bir diğer şekil ise burada mevcut.




Bir diğer şekili ise buradan aldım.



Mode 1 : Askeri amaçla kullanılır. 32 tane cevap seçeneği vardır (00-39 oktal değerleri arası veya 0-31 decimal değer arası). Askeri uçağın ne tür veya nasıl bir görev sebebiyle uçtuğunu belirtir. Normalde barış zamanı pek kullanılmaz.

Mode 2 : Askeri amaçla kullanır ve uçağın kuyruk numarasını belirtir. 4096 tane cevap seçeneği vardır (0000-7777 oktal değerleri arası). Normalde uçuş sırasında değiştirilmez.

Mode 3/A : Sivil amaçla kullanılır. Uçağın bulunduğu bölgei denetleyen Air Traffic Control (ATC) tarafından verilir.(Askeri ve sivil). Uçuş sırasında ATC'nin talebi üzerine değiştirilir.
Bazı Mode 3/A değerleri özel anlam taşımaktadır. Örneğin
  • 7700 Acil Durum (Emergency), 
  • 7600 Telsiz Bozulması (Radio Failure), 
  • 7500 Uçak Kaçırma (Aircraft hijacking)
 anlamlarına gelir.  Daha detaylı bilgi için Transponder (aviation) başlıklı yazıya göz atabilirsiniz.

Mode 3/B : Bu mod kullanılmamaktadır

Mode 3/C : Uçaktaki altimetre cihazının okuduğu  yükseklik değerini belirtir (Askeri ve sivil). Altimetre Ortalama Deniz Seviyesine (Mean Sea Level) olan yükseliği okur. Transponderlarda Mode 3/C bilgisinin gönderilmesi bir düğme ile kontrol edilebilir. Yani ATC'nin talebi üzerine sadece Mode3/A etkinleştirilip  Mode3/C bilgisinin gönderimi kapatılabilir. Mode 3/C anladığım kadarıyla 25 feet çözünürlüğe sahip.

 Mode 3/D : Bu mod kullanılmamaktadır

Mode 4 : Askeri amaçla kullanılır ve şifrelidir. Uçağın dost veya düşman olduğunu ayırt etmeye yarar.

Mode S : Uçak hakkında bilgi verir (Askeri ve sivil)
Mode S Aircraft ID uçuştan önce verilir.
Mode S Aircraft Address uçağa gömülü,  değişmeyen bir numaradır.Uçaklara yavaş yavaş takılıyor.

Mode 5 :  Mode 4 gibi şifrelidir. Uçağın dost veya düşman olduğunu ayırt etmeye yarayan Mode 4'ten daha yeni bir sistemdir . Burada Mode 5 ile ilgili bir sunum var. Buradaki bir yazıda Aselsan tarafından 2013 yılında Mode 5 sisteminin üretildiği haberi var.

Aşağıda bir IFF cihazı resmi var. IFF Mode alanları cihazın üzerinde görülebilir.


IFF Antenleri

IFF antenleri uçaklarda çok farklı yerlerde olabiliyor.

F-15'in IFF antenini gösteren şekil aşağıda ve buradan aldım.. Hem üstte hem de altta iki anten var.


F-16'nın IFF antenini gösteren şekil aşağıda ve buradan aldım.


Gripen'in antenini gösteren şekli ise buradan aldım.


Kokpitteki IFF cihazının bir örneği aşağıda ve buradan aldım. Bu cihazda Mode1,Mode2,Mode3,Mode C,Mode4 ve Mode5 ayarları görülebiliyor.

Netaş'ın sunumunu okurken şöyle bir sunumla karşılaştım. Önemli olduğunu düşündüğüm kısımları aşağı ekliyorum. Netaş'ın IFF cihazları ile ilgili üretimi olduğınu bilmiyordum.



Daha sonra Netaş'ın IFF teknolojisini transfer ederek yurt içinde üretim ve bakım yeteneğini kazandığını okudum. Bu kapsamda AN/TPX-54 IFF sorgulayıcı (interrogator) ve AN/APX-100 IFF cevaplayıcıyı birçok sisteme entegre etmişler.