Menu

25 Mayıs 2009 Pazartesi

Java`da Dosya okuma-yazma

Merhaba, Bu yazimizda java.io paketi icersinde yer alan File, FileInputStream, FileOutputStream`leri nasil kullanacagimizi gorecez. Oncelikle okuma isleminde baslayalim.
Bunun icin bir tane Test classi acip butun denemelerimizi onun uzerinde yapalim.

public class Test {

public static void main(String[] args) throws FileNotFoundException, IOException{

File file = new File("d:\\testimg\\okunan.GIF");

FileInputStream fin = new FileInputStream(file);

byte[] okunan = new byte[(int)file.length()];

fin.read(okunan);

String veri = new String (okunan);

System.out.println(veri);

fin.close();

}
}

Yukaridaki ornekte, File interfacesini kullanarak okunancak olan dosyanin yolunu gosteriyoruz, daha sonra bunu bir stream icine aliyoruz ve byte[] dizisi seklinde byte tipinde aliyoruz, burada length ile dosyanin uzunlugu int tipinde aliyoruz, daha sonra read metodu ile okuyoruz, ve String tipinde okunan`i alip islemi bitiyoruz... ve tabikii close(); kullanmayi unutmuyoruz :).

Simdide Yazma islemini yapalim....
Yukaridaki yaptigimiz isin nerdeyse aynisi:)


String deger = "Merhaba Dunya";
FileOutputStream yaz = new FileOutputStream("D:\\testimg\\yazilan.txt");
yaz.write(deger);

bu kadar.

Simdi ise, bir dosyadaki verileri baska bir dosyaya yazalim, ve bir resim dosyasinin aynisindan bir tane daha olusturalim bir nevi kopyalama islemi :)

public class Test {

public static void main(String[] args) throws FileNotFoundException, IOException{

File file = new File("d:\\testimg\\dukesign.GIF");

FileInputStream fin = new FileInputStream(file);

byte[] okunan = new byte[(int)file.length()];

fin.read(okunan);

FileOutputStream yaz = new FileOutputStream("D:\\testimg\\dukesign10.txt");

yaz.write(okunan);

fin.close();

}
}

Yukaridaki ek olarak, birde, bir dosyadan veri okuyup onu baska bir dosyaya nasi yazacagimizi ornkle gosterlim.

public static void main(String[] args) throws FileNotFoundException, IOException{

// Burada dosyayi okuma islemini baslatiyoruz.
File file = new File("d:\\testimg\\okunan.txt");

FileInputStream fin = new FileInputStream(file);

byte[] okunan = new byte[(int)file.length()];

fin.read(okunan);

String veri = new String (okunan);

System.out.println(veri);

// burdan sonrada dosyayi baska bir dosyaya yazmaya islemi basliyor
byte f[]=veri.getBytes();

OutputStream os = new FileOutputStream("d:\\testimg\\okunan2.txt");
for(int i=0; i
os.write(f[i]);
}

fin.close();
os.close();

}


Umarim faydali olmusutur.
- Bu dokumani istediginiz yerde yayinlayabilirsiniz :)


Temp`de directory yaratmak ve dosya olusturmak...

String path = System.getProperty("java.io.tmpdir");
        File dir = new File(path + "\\folder");
        dir.mkdirs();
        File f = File.createTempFile(reportName, ".jrxml", dir.getCanonicalFile());

        FileOutputStream fos = new FileOutputStream(f);
        fos.write(rm.getReportContent(report));

13 Mayıs 2009 Çarşamba

Ornek bir Web Service

Merhaba, bu yazimizda olusturdigumuz bi entity`in beanlerini olusturmak, daha sonra o bean`i web service yapalim.
Yaptigim ornek herhangi bir turde string deger alsin (XML, html vs.), ve geriye yine bir string deger dondursun. bean`imizin iki tane metodu olsun, getConfig ve setConfig. getConfig String tipinde bir parametre, setConfig String tipinde iki tane parametre alsin. Simdi sozu fazla uzatmadan hemen entity ve class`larimizi olusturalim.

Config.java
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class VConfig implements Serializable {
@Id
private String name;
@Column(nullable=true,columnDefinition="CLOB")
private String xmlData;

public VConfig(){
}

public VConfig(String name,String xmlData){
setName(name);
setXmlData(xmlData);
}

public String getXmlData() {
return xmlData;
}

public void setXmlData(String xmlData) {
this.xmlData = xmlData;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

ConfigWSRemote.java
import javax.ejb.Remote;
@Remote
public interface VConfigWSRemote {
StringWrapper getConfig(String name);
void setConfig(String name, String config);
}

ConfingWS.java
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.config.entity.VConfig;

@WebService
@Stateless
public class VisaConfingWS implements VConfigWSRemote {
@PersistenceContext
EntityManager em;
@WebMethod(action="getConfig")
public StringWrapper getConfig(String name) {
VConfig vConfig = (VConfig) em.createQuery("SELECT v FROM VConfig v WHERE v.name = :name"). setParameter("name", name).getSingleResult();
return new StringWrapper(vConfig.getXmlData());
}

@WebMethod(action="setConfig")
public void setConfig(String name, String config){
VConfig vConfig = new VConfig(name,config);
try{
em.merge(vConfig);
}catch(IllegalStateException ie){
try{
em.persist(vConfig);
}catch(Exception e){
e.printStackTrace();
}
}catch(Exception e){
e.printStackTrace();
}
}
}

Simdir bir tanede StringWrapper class`i olusturaluim cunku, xml veya bask turde bir veri girildiginde hata vermeye ama, getConfig ile cagrildiginda, xml okunamayacak o yuzden bole bir class olusturalim ve return new StringWrapper(vConfig.getXmlData()); bu satirtdaki gibi donen deger StringWrapper tipinde donsun, bu sekilde yapinca hic bir sorun yasanmayacaktir.

StringWrapper.java
import java.io.Serializable;
public class StringWrapper implements Serializable{
protected String content;

public StringWrapper(){}

public StringWrapper(String content) {
setContent(content);
}

public void setContent(String content) {
this.content = content;
}
public String getContent(){
return this.content;
}
}

Bu sekilde sade bir class.
Artik web servisimiz hazir, tek yapmak gerekn wsdl`ini cagirmak ve kullanmak :)

Not: Web servisimizin metodunun action`i gostermeliyiz, java ile calisirken hic bir sorun yasanmaz, ancak baska bir dilden cagirirken, mesala .NET vs. action`i gostermediginiz surece metodu gormeyecektir.

9 Mayıs 2009 Cumartesi

Entity`de inheritance

Java Entity classları, Java Object Mapping teknolojisi sayesinde database deki tabloları oluşturmakta, bu da aslında object oriented ın nimetlerinden olan polymorphism’in nasıl tablolara yansıdığı sorusunu akla getirmekte. Teorik bilgim olmasına rağmen, bu yazımı yazarken bazı küçük testler yaparak teorik bilgimin ne kadar doğru olduğunu göreceğim.
Şimdi işe deneme amaçlı bir entity sınıfı yazarak başlayayım ve jpa daki default inheritance türü olan SINGLE TABLE ı incelemeye başlayalım.
AbstractEntity sınıfı
package Entities;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name="Abstract_Entity")
@Entity
public class AbstractEntity implements java.io.Serializable {

@Id
private Long id;

private String commonAttribute;


public String getCommonAttribute() {
return commonAttribute;
}

public void setCommonAttribute(String commonAttribute) {
this.commonAttribute = commonAttribute;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

}
yukarıda basit bir sınıf yarattım, bu sınıf diğer sınıfların “extend” edeceği, super sınıf. Annotation’larla default değer değiştirilmediyse jpa nın kullanacağı inheritance strategisi single table, şimdi diğer alt sınıfları da yaratalım.
package Entities;

import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.OneToMany;

@Entity
public class ATypeEntity extends AbstractEntity implements java.io.Serializable{
@OneToMany
private List attributes = new ArrayList() {};

public List getAttributes() {
return attributes;
}

public void setAttributes(List attributes) {
this.attributes = attributes;
}

}

package Entities;

import javax.persistence.Entity;
@Entity
public class BTypeEntity extends AbstractEntity implements java.io.Serializable{
private int bTypeEntityAttribute;

public int getBTypeEntityAttribute() {
return bTypeEntityAttribute;
}

public void setBTypeEntityAttribute(int bTypeEntityAttribute) {
this.bTypeEntityAttribute = bTypeEntityAttribute;
}
}
package Entities;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class AttributeEntity implements java.io.Serializable {
@Id
private Long id;

private String attribute;

public String getAttribute() {
return attribute;
}

public void setAttribute(String attribute) {
this.attribute = attribute;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}
}

ATypeEntity ile BTypeEntity AbstractEntity sınıfından türetildiler, yani AbstractEntity nin id ve commonAttribute değişkenleri her ikisinde de var. ATypeEntity nin bunun yanında one to many bir ilişkisi var, BTypeEntity nin ise kendine özel bTypeEntityAttribute adında bir değişkeni var.
Single Table stratejisinden beklediklerim!
Tüm bu ilişkileri tek bir tabloda toplamalı
Tablo içinde bir sütunla tablodaki satır’ın hangi objeye ait olduğunu söylemeli
  • Tüm sınıflar aynı tabloda tutulduğu için mesela BTypeEntity e ait bir değişken, ATypeEntity e ait bir satırda boş bırakılmalı.
Şimdi programı çalıştırıp, görelim

database schema
Yukarıda tam istediğim şekilde database yapısını oluşturdu. Bir kaç değer girdiğimde ise Dtype sütunun satırın ait olduğu objenin sınıfını belirtmek için kullanıldığını, diğer alanların ise boş kaldığını gördüm, böylece “single table” aslında tam beklediğim gibi çalısıyor.
Şimdi biraz bu strateginin avantajları dezavantajları üzerinde düşünelim,
Buradaki en büyük dezavantaj sınıfların sahip olmadıkları değişkenler içinde database de yer tutmaları ayrıca database deki satırların büyük boyutlu olması da iyi birşey değil. Ama yine de bu yöntem gayet basit ve tek satırla tüm bilgi alınabiliyor.
Not nullable sütunlar kavramı
Eğer her sınıfın değişkenleri tek tabloda tutuluyorsa, bir sınıf kendisine ait olmayan değişkenleri null yani boş olarak bırakıyor, bu durumda “not nullable” yani boş bırakılamaz değişkenler tanıtamıyoruz çünkü diğer bir sınıf kendisine ait olmayan bu değişken için “null” olarak tabloya girecek.
Simdi ikinci yönteme geçelim, “JOINED”
Burada yöntemimizi değiştirebilmek için tek yapmamız gereken, AbstractEntity sınıfına @Inheritance annotation ı ile strategimizi değiştirmek.
package Entities;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import  javax.persistence.InheritanceType;
import javax.persistence.Table;

@Table(name="Abstract_Entity")
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class AbstractEntity implements java.io.Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String commonAttribute;

public String getCommonAttribute() {
return commonAttribute;
}

public void setCommonAttribute(String commonAttribute) {
this.commonAttribute = commonAttribute;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

}

Şimdi benim JOINED strategisinden beklediklerim,
  • Her sınıfın ayrı bir tablosu olacak
  • Her sınıfın ayrı tablosunda sadece kendisiyle ilgili değişkenler tutulacak
  • Tablolar kendi aralarında JOIN sütunuyla ilişkilendirilecek.
Kodu çalıştırdığımda karşıma şu şekil bir database yapısı çıkıyor.

Database Schema Joined

Resimden görüldüğü gibi her sınıfın ayrı tabloları oluşmuş ve her tablo kendi sınıfıyla ilgili değişkenleri tutuyor. Bu yapıda mesela ATypeEntity sınıfına ait bir obje istendiğinde, AbstractEntity ve ATypeEntity e ait tablolar aralarında join yaparak bu obje oluşturulacaktır.

Bence bu yöntem object oriented mantığına daha çok uymakta, fakat her obje için join yapılmakta, eğer sınıflar arasında fark fazlaysa bence bu yöntem ilk yöntemimiz olan “single table” a göre daha uygun. Fakat her obje için sorgunun maliyeti joinlerden dolayı biraz fazla.

JPA nın inheritance için sunduğu son yöntem ise “Table Per Class” yani Türkçesiyle her sınıf için bir tablo. Bu yöntemden beklediklerim,
  • Tüm sınıfların ayrı tablosu olması fakat ayrıca bir sınıfa ait bir tablonun türediği sınıfa ait olup kendisine geçen değişkenler içinde yer tutmasıdır.
Burada aklıma gelen soru ise aslında eğer gerçekten her sınıfın tablosu üretilecekse bizim AbstractEntity sınıfınında tablosu üretilecek mi? Benim örneğimde soyut (abstract) bir sınıf değil ama gerçekte bu sınıfta soyut olabilirdi. Burada AbstractEntity sınıfını soyut sınıf yapıp, inheritance strategimi değiştirmeye karar veriyorum ki sorularım cevap bulabilsin ve kodumu aşağıdaki şekilde değiştiriyorum.
package Entities;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import  javax.persistence.InheritanceType;
import javax.persistence.Table;
@Table(name="Abstract_Entity")
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractEntity implements java.io.Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String commonAttribute;

public String getCommonAttribute() {
return commonAttribute;
}

public void setCommonAttribute(String commonAttribute) {
this.commonAttribute = commonAttribute;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

}

Table per class inheritance is not supported. Entity class [class Entities.AbstractEntity]. Hatasını alıyorum. Bu mesaj bana toplink in “table_per_class” ı desteklemediği izlenimine kapılıyorum. Yazımı burada sonlandırıyorum, çünkü elimde toplink ten başka jpa implementasyon paketi yok ve sorularım cevapsız kalıyor ne yazık ki.

7 Mayıs 2009 Perşembe

JAVA İLE .NET'İ KONUŞTURMAK

Bu yazımızda java ile basit bir web servisi yazıp .net ile bu servise erişmeyi anlatacağız.



Kullandığımız araç gereç ve platformlar:

1.) Sun Application Server 8.1

Download : http://java.sun.com/j2ee/1.4/download.html#sdk

2.) NetBeans IDE 4.1

Download : http://www.netbeans.org/downloads/index.html

3.) MySQL 4.1 ve MySQL Connector/J

Download : http://dev.mysql.com/downloads/

4.) Microsoft Visual Studio 2003

Download : http://msdn.microsoft.com/vstudio/



Java ile ilgili hemen heryerde karşılaşılan temel sorunları da bu yazı ile dile getirmeye çalışalım. Java ile başlangıç düzeyinde ilgilenenlerin en büyük sıkıntısı CLASSPATH ayarlarıdır ve bu sorunun hemen her kaynakta farklı çözümleri bulunmaktadır. Benim önereceğim çözüm de farklı olacak , çünkü önerdiğim Sun Application Server C:\Sun dizinine kendi JDK , J2EE ve JRE'sini kuruyor. Siz bu yazılımı yükleyerek aslında J2ME hariç komple Java Platformunu yüklemiş oluyorsunuz. Sun Java System Application Server'ı yükledikten sonra Bilgisayarım üzerinde sağ tuş -> Gelişmiş sekmesindeki ortam değişkenlerinde Sistem değişkenleri bölümünde yeni bir Sistem değişkeni tanımlayarak adına CLASSPATH diyelim ve Değişken değeri olarak aynen şunları yazalım : C:\Sun\AppServer\jdk\bin;C:\Sun\AppServer\jdk\jre\bin;C:\Sun\AppServer\jdk\jre\lib;C:\Sun\AppServer\jdk\jre\lib\ext;C:\Sun\AppServer\jdk\jre\lib\ext;C:\Sun\AppServer\jdk\bin;C:\Sun\AppServer\lib



Bu ortam değişkenleri Java'nın ihtiyaç duyduğu bütün kitaplıkları yükler. Daha sonra siz istediğiniz veritabanı sürücüsünü burada belirtilen C:\Sun\AppServer\jdk\jre\lib\ext dizinine atarsınız ve bu dizin tanımlı olduğu için veritabanı sürücünüz de uygulamalarınız tarafından çalıştırılabilir.Dolayısıyle MySQL sürücüsünü de bu dizine koplayamanız gerekiyor.



Veritabanı, uygulama sunucusu ve web servisi için Java idelerinin belki de en başarılısı olan NetBeans dışında herhangi birşeye ihtiyacımız bulunmuyor , ancak bu IDE'de Java ile ilgili bütün işlerimizi yapabilmek için bazı tanımlamalar yapmamız lazım.



Önce Sun Application Server'ı NetBeans'e tanıtmamız gerekiyor. Bunun için Tools -> Server Manager yolundan giderek Açılan Server Manager Penceresinde AddServer diyelim. Gelen pencerede admin kullanıcı adı ve parolasını yazdıktan sonra Sun Application Server artık NetBeans IDE ile bütünleşik çalışmaya başlayacakıtır.







MySQL sunucusunu NetBeans IDE'ye tanıtmak için de benzer bir yol izliyoruz.Sol taraftaki Runtime arabiriminde bulunan Databases bölümündeki Drivers'e sağ tuş ile tıklayıp Add Driver komutu veriyoruz. Gelen pencerde Add bunonuna tıklayarak C:\Sun\AppServer\jdk\jre\lib\ext\ yolunda bulunan mysql-connector-java-3.1.10-bin.jar driverını gösteriyoruz.

Dikkat : Bu sürücü dışındaki sürücüler MySQL 4.1'de Türkçe karakter problemi çıkarıyor.Bu sürücü ile MySQL character set'inizi latin5 olarak ayarlayabilirsiniz.







MySQL sürücüsünü tanıttıktan sonraki durum







Bu aşamalardan sonra şimdi bilgisayarımızda kurulu bulunan MySQL sunucusuna bağlanmamız gerekiyor. Bu işlem için Databases/Drivers/MySQL(MM.MySQL driver) bölümünde sağ tuş ile Connect Using komutu verelim.







Artık btturk isimli bir veritabanımız var ve bu veritabanında NetBeans ile bilgiler isimli bir tablo oluşturabiliriz.













Evet bilgiler isimli tablomuzu oluşturduk ve içerisine okuyacağımız verileri de yazdık.Şimdi web servisimizi yazmaya başlayabiliriz.Web servisi için önce bir web uygulaması projesi başlatmamız gerekiyor. NetBeans menüsünden File -> New Project yolunu izliyoruz.Projemiz bir web uygulaması ve adı da webServisiDeneme1









Projeyi oluşturduktan sonra Web Servisinin çalışacağı java package'ı oluşturmamız gerkiyor.İşlemin nasıl yapıldığı resimlerde görülebilir.









WebServisi isimli package'i oluşturduktan sonra bir web servisi yaratabiliriz.Bu işlem ekran görüntüleriyle gösterilmiştir:









Personel Web Servisini oluşturduktan sonra servis üzerinde sağ tuş->Add Operation... komutu veriyoruz.







Operasyonumuz sonucunda bize personel bilgilerinin String türünden dönmesini istediğimiz için Return Type'ı String olarak seçiyoruz.







Parametre olarak göndereceğimiz değerin veritabanındaki id alanına denk gelmesi nedeniyle parametre ekleme işleminde int değer göndermemiz gerekiyor. Bu işlem için Add Operation penceresinde Add tuşuna tıklayarak parametre tipi olarak int ve parametre ismi olarak id yazıyoruz. Web servisimiz çalıştığında oluşacak WSDL dökümanında bu değerler gidip gelecektir.







Bu işlemlerden sonra projemizin görüntüsü aşağıdaki gibi olacaktır:







Şimdi SQL bağlantımız için gerekli kodları yazabiliriz :

Yeni bir java class oluşturarak adını SQLSorgulari verelim ve içerisine şu satırları yazalım :



package WebServisi;

import java.sql.*;

public class SQLSorgulari {



public SQLSorgulari() {

}



public String bilgiDondur(int id) throws Exception{

Class.forName("org.gjt.mm.mysql.Driver");

java.sql.Connection baglanti = DriverManager.getConnection("jdbc:mysql://localhost/btturk","root","");

java.sql.Statement sorgulama = baglanti.createStatement();

java.sql.ResultSet veriler = sorgulama.executeQuery("SELECT * FROM bilgiler where id="+id);

String bilgiler=null;

while (veriler.next()){

bilgiler = veriler.getString(1)+" "+veriler.getString(2)+" "+veriler.getString(3);

}

return bilgiler;

}



}



Bu sınıf sadece SQL sorgusu sonucunda dönecek değer için bağlantıları sağlamakta ve bilgiDondur() metodunu yazmaktadır bu metodun tek yaptığı kendisine gelen int türünden değeri veritabanında aramak ve String türünden bir veri döndürmektir. Buna benzer java veritabanı örnekleri heryerde bulunabileceği için üzerinde fazla durmuyoruz. Asıl işimiz PersonelImpl.java ile. Bu sınıftan bilgiDondur metodumuzu çağırmamız gerekiyor. Web servisini oluştururken iki dosya oluşmuştu biri PersonelImpl.java ve diğeri PersonelSEI.java bu iki dosyadan PersonelSEI.java sadece PersonelImpl.java sınıfındaki metodları java.rmi ile sunma işi yapmaktadır.Asıl metodun tanımlama yeri PersonelImpl.java'dır ve buradan SQL medodumuzu çağırmamız gerekiyor.



PersonelImpl.java sınıfına gidip aşağıdakileri yazalım :



package WebServisi;

//SQL metodumuzu barındıran sınıfı çağırıyoruz

import WebServisi.SQLSorgulari;

public class PersonelImpl implements PersonelSEI {



SQLSorgulari SQLSorgu= new SQLSorgulari();//SQLSorgulari isimli sınıfın bir örneğini yarattık



public String bilgiGetir(int id){

try{

return SQLSorgu.bilgiDondur(id);//bilgiDondur isimli metodu çağırıyoruz

}catch(Exception hata){

return "hata";

}

}



Web servisimiz tamam artık uygulamayı run edebiliriz. F6 tuşuna basarak uygulamayı çalıştırıyoruz. Bu esnada uygulama derlenmekte, WAR dosyası olarak birleştirilmekte ve uygulama sunucusunda deploy edilmektedir. Browser'ımızı açıp http://localhost:8080/webServisiDeneme1/Personel?WSDL yazarsak çalışan web servsinin WSDL dökümanını görebiliriz.







Şimdi Java ile web servisimizi yazdık ve bunu .NET içerisindeki bir uygulamadan kullanmamız gerekiyor. Bu iş için Visual Studio açmak gerektiği için NetBeans'i ve bilimum açık programınızı kapatmanızı öneriyorum çünkü zaten Sun Application Server epey fazla RAM tüketiyor.Yalnız dikkat edilmesi gereken nokta şu ki eğer Sun Application Server'ı NetBeans üzerinden Start ettiyseniz NetBeans'i kapattığınızda Sun Application Server de kapanacaktır. Böyle bir durumda Başlat->Programlar->Sun Microsystems->Application Server PE ->Start Default Server ile uygulama sunucusunu yeniden çalıştırmanız gerekebilir.



Eski ve daim dostumuz Visual Studio 2003 'ü açıyoruz ve yeni bir proje oluşturuyoruz.Projenin adı da JavaDotnet ve bu bir Visual Basic .NET projesi. Aslında uygulamayı C# ile de yazabilirdik fakat o zaman Java ile Java konuşuyormuş gibi bir durum ortaya çıkabileceği için iki farklı teknolojinin daha iyi farkedilmesini sağlamazdı.







Oluşturduğumuz uygulamaya iki label ve iki metin kutusuyla bir de buton ekliyoruz.







Web Servisimizi .Net projesine bir Web Referansı olarak ekliyoruz .







Görüldüğü gibi Web Servisimiz ve bilgiGetir() metodumuz Visual Studio tarafından görüldü.







Web Referansını ekledikten sonra projemize geri dönüyoruz ve Web Servisi nesnesinin örneğini oluşturuyoruz. Ben bu örneği public olarak tanımladım ama genelde örneklerde tıklama olayının (event'ın) içinde Dim ile tanımlandığını görüyoruz. Bu web servisinin bize sağladıklarını başka form elementlerinde kullanmak gerekebileceği için bence bunu bir üst scope'ta tanımlamak daha iyi.







Yine bir nesnenin bizden neler isteğini ve bize ne vereceğini görmenin en iyi yolu olarak iki öneri sunabilirim . Biri WSDL dökümanını incelemek bir diğeri de örneklediğimiz nesnenin metod veya özelliklerini anlamak için yanına bir nokta koymak. Örneğimiz için gösterecek olursak :





personel nesnemizin bilgiGetir metodu bizden localhost.bilgiGetir türünden bir değişken istiyormuş ve karşılığında da localhost.bilgiGetirResponse tipinde bir yanıt döndürüyormuş.O halde bizim bu tipten değişkenler oluşturmamız gerekiyor. Biz de bu değişkenleri tanımlıyoruz :



Public personel As New localhost.Personel

Public bilgiGiden As New localhost.bilgiGetir

Public bilgiGelen As New localhost.bilgiGetirResponse



Butonun tıklama olayına aşağıdakileri yazdığımızda uygulamamız çalışacaktır :



Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim texteYazilan As Integer = CType(TextBox1.Text, Integer)

bilgiGiden.int_1 = texteYazilan

bilgiGelen = personel.bilgiGetir(bilgiGiden)

TextBox2.Text = bilgiGelen.result

End Sub



5 Mayıs 2009 Salı

Java Persistence API

Java persistence api java geliştiricilerine uygulamalarında kullanacakları veriye nesne
göreli olarak erişim imkanı sunar. Java persistence üç ana alana ayrılır:
• Java Persistence API
• Java sorgu dili
• Fiziksel veriyi nesne gцreli eşleme
1- Entity
Entity java persistence ın tanım nesnesidir. Genel olarak Entity göreli veri tabanında
tablolara karşılık gelir ve her Entity örneği bu tabloda bir satırı ifade eder. Bir varlığın
persistent durumunu Entity ilgili alanları yada özellikleriyle belirlenir. Bu alanlar ve
özellikler Entity belleklerde tutulan verilerle eşlenmesi için nesne/göreli eşleme
yöntemlerini kullanırlar.
1.1- Entity Sınıflarının Gereksinimleri
Bir varlık sınıfı şu gereksinimleri izlemelidir:
• Sınıf javax.persistence.Entitiy bilgilendirmelerine uymalıdır.
• Sınıfın public veya private argümansız bir yapılandırıcısı olmalıdır. Sınıfın
bunun dışında başka yapılandırıcıları da olabilir.
• Sınıf final tanımlanmamalıdır. Hiçbir metot ve persistence bağımlı değişken
final tanımlanmamalıdır.
• Eger sınıfın bir kopyası ayrı bir nesne gibi bir değer olarak atanmak isteniyorsa
bu sınıf Serializable ara yüzünü gerçekleştirmelidir.
• Entity sınıfları hem Entity sınıflarını hem de diğer sınıfları extend edebilir. Diğer
sınıflar da varlık sınıflarını extend edebilirler.
• Persistence ilişkili değişkenlerin tümü private, protected yada paket içi private
olarak tanımlanmalıdır ve direk erişimleri sınıf içi metotlarla olmalıdır.
1.2- Entity Sınıfında Persistence İlişkili Alanlar ve Özellikler
Entity persistence durumu o Entity değişkenleri veya JavaBeans-style özellikleri
tarafından erişilebilirdir. Bu alanlar ve özellikler şu türlerde olmalıdır:

• Java İlkel Türleri
• Java.lang.String
• Diğer Türler:
o Java.math.BigInteger
o Java.math.BigDecimal
o Java.util.Date
o Java.util.Calendar
o Java.sql.Date
o Java.sql.Time
o Java.sql.TimeStamp
o Kullanıcı tanımlı türler
o byte[]
o Byte[]
o char[]
o Character[]
• Sayılı türler
• Diğer Entity ve/veya Entity grupları
• Gömülü sınıflar
1.2.1- Persistent Alanlar
Eger Entity sınıfı persistent alanlar içeriyorsa, Persistence çalışma zamanı
Entity sınıfı değişkenlerine doğrudan erişebilir.
1.2.2- Persistent Özellikler
Eger Entity sınıfı persistent özellikler içeriyorsa, Entity JavaBeans in metot
çevirimlerini takip etmelidir. JavaBeans-style özellikleri getter ve setter methodları
kullanır. Bu metotların isimleri Entity sınıfının değişken isimlerinden sonra tanımlanır.
Her özellik için bir getter (getProperty) ve setter (setProperty) bulunur. Tek değerli
özellikler için method şekli şöyledir:
Type getProperty()
void setProperty(Type type)

Entitylarda Birincil Anahtarlar

Her Entity bir tek nesne tanımlayıcısına sahiptir. Örneğin bir tüketici Entityı
tüketici numarası ile simgelenir. Birincil anahtarlar istemcilerin ilgilendikleri Entity
nesnesine ulaşmalarını sağlar. Her Entityın bir birincil anahtarı olmak zorundadır. Bir
Entity basit yada bileşik birincil anahtara sahip olabilir. Basit birincil anahtarlar
javax.persistence.Id notasyonunu kullanırlar. Bileşik birincil anahtarlar bir birincil
anahtar sınıfında tanımlanmalıdır. Bileşik birincil anahtarlar
javax.persistence.EmbeddedId ve javax.persistence.IdClass notasyonlarını
kullanırlar.
Birincil anahtarlar veya bileşik anahtarların özellik yada alanları şu türleri
kullanmalıdır:
• Java İlkel Türleri
• Java.lang.String
• Java.util.Date
• Java.sql.Date
Kayan noktalı gösterim birincil anahtarlar için asla kullanılmamalıdır.
1.3.1- Birincil Anahtar Sınıfları
Bir birincil anahtar şu özellikleri karşılamalıdır:
• Sınıfın erişim tanımlayıcısı public olmalıdır.
• Цzellik tabanlı erişim kullanılıyorsa sınıfın özellikleri public yada protected
olmalıdır.
• Sınıfın bir public yapılandırıcısı olmalıdır.
• Sınıf hashCode() ve equals(Object other) metotlarını gerçekleştirmelidir.
• Bileşik birincil anahtarlar çoklu alan ve özelliklerle eşleşmiş olarak yada
gцmьlebilir sınıf şeklinde ifade edilmelidir.
• Eger birincil anahtar sınıfı bir Entityın alanları yada özellikleriyle eşleşmişse,
birincil anahtar sınıfının özellikleri ve alanlarının isimleri ve türleri o Entity
kümesinin isimleri ve türleriyle uyuşmalıdır.


Varlıklarda Çokluk Bağıntısı

Entitylarda 4 çeşit çokluk vardır. Bire bir, bire çok, çoğa bir ve çoğa çok.
Bire-bir ilişki : Her Entityın bir özelliği başka bir bağıntının sadece tek bir özelliği ile
eşleştirilmişse bire bir ilişki vardır denir. Bire bir ilişkiler javax.persistence.OneToOne
biçimini kullanırlar.
Bire-çok ilişki : Bir Entityın bir özelliği bir başka Entityın birden fazla alanı ile
ilişkilendirilmiş olabilir. Bire çok ilişkiler javax.persistence.OneToMany biçimini
kullanırlar.
Çoğa-bir ilişki : Bir Entityın birçok özelliği bir başka Entityın yalnız bir alanı ile
ilişkilendirilmiş olabilir. Bu durumda çoğa bir ilişki vardır denir. Çoğa bir ilişkiler
javax.persistence.ManyToOne biçimini kullanırlar.
Çoğa-çok ilişki : Bir Entityın birçok özelliği bir başka Entityın birden fazla alanı ile
ilişkilendirilmişse çoğa çok ilişkiden söz edilir. Çoğa çok ilişkiler
javax.persistence.ManyToMany biçimini kullanırlar.
1.5- Varlık Bağıntılarının Yönü
Varlıklar arası ilişkiler iki yönlü yada tek yönlü olabilir. iki yönlü ilişkiler hem sahip
taraf hem de ters tarafa sahiptir. tek yönlü ilişkilerde ters taraftan söz edilmez,
yalnızca sahip taraf vardır. Persistence ın ilişkiye dair günlemeleri veri tabanında
nasıl yapacağı sahip tarafa bağlıdır.
1.5.1- İki Yönlü İlişkiler
İki yönlü ilişkilerde her Entityın başka bir Entitya ilişkin alan yada özelliği
bulunur.
İki yönlü ilişkiler şu kurallara uymalıdır:
• İlişkinin ters tarafı mappedBy elemanı kullanılarak sahip tarafa ait olmalıdır.
• Çoğa çok ve çoğa bir ilişkilerin çok tarafları mappedBy elemanı tarafından
tanımlanmamalıdır. Çok taraf her zaman sahip taraf olmalıdır.
• Bire bir iki yönlü ilişkilerde sahiplik yabancı anahtara sahip olan tarafa aittir.
• Çoğa çok ilişkilerde her iki yön de sahip taraf olabilir.


1.5.2- Tek Yönlü İlişkiler
Tek yönlü ilişkilerde yalnızca bir varlığın ilişki alanı yada özelliği bulunur. İlişki
alanı bulunan Entity ilişkili olduğu varlıktan haberdardır fakat ilişkili olunan Entityın
ilişki alanı olan Entitytan haberi olmaz.

2- Entity Manager

Varlıklar Entity Manager tarafından yönetilirler. Entity Manager
javax.persistence.EntityManager örnekleriyle ifade edilir. Her bir Entity Manager
örneği persistence bağlamlarıyla birleşirler. Persistence bağlamının görev aralığının
içinde varlık örneklerinin yaratılması , üstelenmesi ve silinmesi bulunur.
2.1- Persistence Bağlamı
Persistence bağlamı, yönetilen varlık örneklerinin oluşturduğu bir yapıdır ve bu
yapı özel bir veri tabanında bulunur.
2.2- Entity Manager
Varlık yöneticisi, varlık örneklerini yaratır ve yok eder. Ayrıca, varlıkları temel
anahtarına göre bulur ve sorguların bu varlıklara uygulanmasını sağlar.
2.2.1- Entity Manager Denetleyici Yönetimi
Herhangi bir varlık yöneticisinin persistence bağlamı denetleyici kullanarak
otomatik olarak çoğalır. Uygulamanın tüm bileşenleri tarafından kullanılan varlık
yöneticisi örneği Java Transaction Architecture (JTA) denilen işlemin içinde bulunur.
JTA işlemi diğer uygulamanın bileşenlerini de işin içine sokar. Bu JTA
işleminin bileşenleri persistence bağlamına erişmek ister. Bunun olması için varlık
yöneticisinin javax.persistence.PersistenceContext aracılığıyla uygulama
bileşenlerine enjekte edilmesi gerekir. Persistence bağlamı JTA işlemi sırasında
otomatik olarak artar ve varlık yöneticisi bu JTA işlemi sırasında Persistence bağlamı
ile aynı persistence parçasını işaret eder. Bu sayede uygulamanın bileşenleri varlık
yöneticisine parametre geçmek zorunda kalmaz sadece JTA işleminde değişiklik
yapmak yeterlidir. Java EE denetleyicileri buradaki yaşam döngüsünü yönetirler.
Entity Manager örnekleminin uygulama bileşenlerine enjekte edilmesi:

@PersistenceContext
EntityManager em;
2.2.2- Entity Manager Uygulama Yönetimi
Persistence bağlamı uygulamanın bileşenlerinde otomatik olarak artmıyorsa
ya da varlık yöneticisinin yaşam döngüsü uygulama tarafından yönetiliyorsa bu
durum ortaya çıkar.
Entity Manager bir uygulama tarafından persistence bağlamına erişmek için
kullanılıyorsa ve JTA işleminde tarafından artırılmıyorsa kullanılır. Başka bir deyişle
Entity Manager yeni ve izole olmuş persistence bağlamını oluşturur.Entity Manager
ve onun yarattığı persistence bağlamı uygulama tarafından yaratılır ve yok edilir.
Uygulamalar javax.persistence.EntityManagerFactory metodunu kullanarak
varlık yöneticisini oluşturur.

@PersistenceUnit
EntityManagerFactory emf;

EntityManagerFactory örneklemi kullanarak varlık yöneticisi oluşturulur.
EntityManager em =emf.createrEntityManager();

2.2.3- Entity Manager Kullanarak Varlıkları Bulmak
EntityManager.find metodu kullanarak varlık biricik anahtarına göre
depolanmış varlıkları buluruz.

@PersistenceContext
EntityManager em;
public void enterOrder(int custID, Order newOrder) {
Customer cust = em.find(Customer.class, custID);
cust.getOrders().add(newOrder);
newOrder.setCustomer(cust);
}

2.2.4- Entity Örneklem Yaşam Döngüsünün Yönetimi
Entitylar üstündeki işlemleri varlık yönetici kopyalarıyla yönetiyoruz. Entity
örneklemleri 4 durumda bulunabilir: yeni , yöneten , silinen ve ayıran durumlar.

Yeni Entity örneklemlerinin persistent kimlikleri yoktur ve Entity bağlamıyla
ilişkendirilecek durumda değillerdir.
Yöneten Entityk örneklemlerinin persistent kimlikleri vardır ve Entity
bağlamlarıyla ilişkilendirilirler.
Ayıran Entity örneklemlerinin persistent kimlikleri vardır ve Entity bağlamıyla
ilişkendirilecek durumda değillerdir.
Silinen Entity örneklemlerinin persistent kimlikleri vardır ve Entity bağlamlarıyla
ilişkilendirilirler
2.2.4.1- Entity Örneklemleri
Yeni Entity örneklemleri persistent metodu tarafından yönetilirler. Yani persist
metodu tamamlanmış işlem gerçekleştiği zaman Entityın bilgileri bir veri tabanında
saklanır.
@PersistenceContext
EntityManager em;
...
public LineItem createLineItem(Order order, Product product,int quantity) {
LineItem li = new LineItem(order, product, quantity);
order.getLineItems().add(li);
em.persist(li);
return li;
}

@OneToMany(cascade=ALL, mappedBy="order")
public Collection getLineItems() {
return lineItems;
}

2.2.4.2- Entity Örnekleminin Silinmesi
Entity örneklemlerinin yönetiminde silme işlemini yapmak için silme metodunu
kullanırız ya da cascade silme işlemini kullanırız. Bunu birebiriyle ilişkili Entitylarda
kullanırız. Eğer bu silme metodu yeni bir Entity tarafından çağırılıyorsa bu komut
askıya alınır. Eğer silme metodu Ayıran bir Entity tarafından çağırılıyorsa bu bir hata
oluşmasına sebep olur ne IllegalArgumentException fırlatır.

Public void removeOrder (Inteder orderId){
try {
Order order =em.find(Order.class,orderId)
em.remove(order);
}
}
2.2.5- Sorguların Oluşturulması
EntityManager.createQuery ve EntityManager.createNamedQuery metotları
Java Persistence sorgulama dillerindeki sorgulamaları kullanarak saklanmış bilgileri
sorgulamak için kullanılır.
CreateQuery metodu dinamik sorgular yaratmak için kullanılır.
public List findWithName(String name) {
return em.createQuery(
"SELECT c FROM Customer c WHERE c.name LIKE :custName")
.setParameter("custName", name)
.setMaxResults(10)
.getResultList();
}
CreateNamedQuery metodu ise statik sorgular yaratmak için kullanılır. Bu sorgular
javax.persistence.NamedQuery de tanımlıdır.
@NamedQuery(
name="findAllCustomersWithName",
query="SELECT c FROM Customer c WHERE c.name LIKE
:custName"
)
Alt tarafta createNamedQuery metodunun kullanımına ait bir örnek var. Bu örnekteki
NamedQuery yukarıda tanımlanmıştır.

@PersistenceContext
public EntityManager em;
...
customers = em.createNamedQuery("findAllCustomersWithName")
.setParameter("custName", "Smith")
.getResultList();
2.2.5.1- Sorgulardaki İsim Parametreleri
Parametre geçiren isimler javax.persistence.Query.setParamater (String
name, Object value) metodu kullanarak sınırlandırılırlar. Aşağıdaki örnekte
findWithName ve setParameter metodu kullanarak parametre geçiliyor.
public List findWithName(String name) {
return em.createQuery(
"SELECT c FROM Customer c WHERE c.name LIKE :custName")
.setParameter("custName", name)
.getResultList();
}
2.2.5.2- Sorgulardaki Durumsal Parametreler
İsim yerine durumsal parametre de kullanılır. Kullanım yapısı (?) den sonra
gelen sayı gelen parametrenin sorgudaki yerini verir.Query.setParameter(integer
position ,Object value) bu metot parametre geçmek için kullanılır.
public List findWithName(String name) {
return em.createQuery(
“SELECT c FROM Customer c WHERE c.name LIKE ?1”)
.setParameter(1, name)
.getResultList();
}
Giriş parametreleri 1. giriş parametrelerinden sıralanmaya başlar.

2.3- Persistence Birimleri
Persistence bolumu varlık yöneticisi örnekleri tarafından yönetilen bütün varlık
sınıflarını tanımlar.Bu Entity grupları tek bir bilgi deposunda bulunan bilgileri temsil
eder.
Persistence bölümleri persistence.xml konfigürasyon dosyası tarafından

tanımlanır.META-INF dizini persistence.xml içeren JAR dosyası ya da dizini,
persistence bölümünün kaynağı olarak adlandırılır.
Persistence bölümünün çalışma alanı persistence bölümünün kaynağı tarafından
belirlenir.Her bir persistence bolumu kendi çalışma alanına özel bir isimle
tanımlanmak zorundadır.
Persistence bölümleri WAR ya da EJB JAR dosyalarını parçası olarak birlikte
kullanılabilir.Ayrıca WAR ya da EAR dosyalarının içine eklenebilecek bir JAR dosyası
olarak da birlikte kullanılabilir.
Eğer persistence bölümünü bir grup olarak bir EJB JAR dosyası içinde
kullanırsanız, persistence.xml EJB JAR in META-INF dizini içine yerleştirilmelidir.
Eğer persistence bölümünü bir grup olarak bir WAR dosyası içinde kullanırsanız,
persistence.xml WAR dosyasının WEB-INF/classes/META-INF dizini içine
yerleştirilmelidir.
Eğer persistence bölümünü WAR ya da EAR dosyası içine dahil edilecek bir
JAR dosyası içinde kullanırsanız, JAR dosyası aşağıdaki bölümlerden birisine
yerleştirilmelidir.
- WAR in WEB-INF/lib dizini
- Bir EAR dosyasının en üst seviyesi
- EAR dosyalarının kütüphane dizini
2.3.1- Persistence.xml Kütüğü
Persistence.xml bir ya da birçok persistence birimi tarafından tanımlanır.
Aşağıdaki örnek bir persistence.xml kütüğüdür.


This unit manages orders and customers.
It does not rely on any vendor-specific features and can
therefore be deployed to any persistence provider.

jdbc/MyOrderDB
MyOrderApp.jar
com.widgets.Order
com.widgets.Customer



Bu dosyanın içinde OrderManagement denilen bir persistence parçası tanımlıdır ve
JTA tarafından kullanılırlar. JAR dosyası ve sınıf elemanları persistence sınıflarını
yönetirler

1 Mayıs 2009 Cuma

Enum

Java'da en cok karsilasilan ve eksikligi hissedilen ozelliklerden birisi C ve C++'ta sikca kullanilan enum operatorudur. Aslinca C tipi enumlar kullanilmasi son derece guvensiz yapilardir. enum sabit degerli bir dizi olusturulur. En cok kullanilan ama kullanilmasi onerilmeyen integer sabitler (C'de oldugu gibi) genellikle java'ya baslayanlarin ilk basvurdugu yontemdir. bu tip enum su nedenlerden oturu sakincalidir.- Typesafe degil, yani kaza ile bir integer bu degerler yerine kullanilabilir. guvensiz kod olusumu- degerlerin basina ek bilgisi eklemek gerekebilir- degerler bilgi verici degil (debug sirasinda ya da log yazilirken sadece rakamlar gorunur.)
public class Almanak {
public static final int MEVSIM_KIS = 0;
public static final int MEVSIM_BAHAR = 1;
public static final int MEVSIM_YAZ = 2;
public static final int MEVSIM_SONBAHAR = 3;
.... }

javada guvenli enum kullanimi icin ciddi tasarim yapmak gerekebiliyordu. Sirf enum siniflari olusturmak icin IDE yazilimlarinda ozel araclar bile kullaniliyor. Normalde guvenli bicimde hakkini vererek gerceklestirmek icin sayfa boyu kod gerektirebilecek oyun kagidi destesi olusturma islemi Java 1.5 typesafe enum, generics ve gelismis for ile asagidaki sekilde kolayca gerceklestirilir. asagida goruldugu gibi sadece enum Tip { maca, sinek, karo, kupa} diyerek dortlu bir kume olusturuluyor. Bu degerler ancak Tip sinifina ait nesnelere atanabilir oldugundan hatali kullanim ihtimali cok dusuktur. Kullanimi da C ve C++'a benzediginden programcilar yabancilik cekmeyecektir. Bu ifadelerin bir switch-case blogunda kullanilmasi da mumkun (bu onceden kodla tasarlanan guvenli enum siniflari icin mumkun degildi)

enum Tip {
maca, sinek, karo, kupa }

enum Deger {
ikili, uclu, dortlu, besli, altili, yedili,
sekizli, dokuzlu, onlu, vale, kiz, papaz, as
}
// desteye kartlari ekle List deste = new ArrayList();
for (Tip tip : Tip.VALUES)
for (Deger deger : Deger.VALUES)
deste.add(new Kart(Tip, Deger));
// desteyi karistir
Collections.shuffle(deste);
Baska bir ornek, bu defa enum sinif oalrak ifade ediliyor. icindeki bilesenlere deger atanabiliyor. Goruldugu gibi sebze enum sinifinda hem sebzeler, hem sebzelerin fiyatlari yuklenebiliyor. Ayrica bu sinifi kullanan yazilimin ikinci parcasinda enum sinifinin switch blogunda nasil kullanilacagi gosteriliyor.

public enum Sebze {
domates(500), salatalik(550), biber(1000), patlican(700);
Sebze( int fiyat) {
this.fiyat = fiyat;
}
private final int fiyat;
public int fiyat () { return fiyat;
}
}
public class SebzeTest { public static void main(String[] args) {
for (Sebze s : Sebze.VALUES)
System.out.println(s + ": \t"
+ s.value() + "bin TL \t" + renk
(s));
}
private enum SebzeRengi {
kirmizi, yesil, mor
}
private static SebzeRengi renk(Sebze s) {
switch (s) {
case domates:
return SebzeRengi.kirmizi;
case patlican:
return SebzeRengi.mor;
case salatalik:
case biber:
return SebzeRengi.yesil;
default:
throw new AssertionError("Bilinmeyen sebze: " + s); }
}
}