Struts 2’de .action uzantısını nasıl silerim?

Struts 2’de her bir Action sınıfını çağırmak için standartta .action uzantısı kullanılır. Başka bir deyişle struts.xml dosyasında Action sınıfını çağırmak için tanımlanan ismin sonuna .action yazılarak istek gönderilir. İsmi “LoginAction” olan bir sınıfın çağrım ismi “login” olarak tanımlanmışsa, istek şu şekilde yapılır :

http://<host&gt;:<port>/<context-path>/login.action

Aynı Servlet sınıflarında olduğu gibi Action sınıflarında da bir mapping uzantısı kullanılabilir.

web.xml dosyasında Servlet mapping aşağıdaki şekilde yapılıyordu :

[codesyntax lang=”xml” lines=”no”]

<servlet>
	<servlet-name>LoginServlet</servlet-name>
	<servlet-class>servlets.LoginServlet</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>LoginServlet</servlet-name>
	<url-pattern>/login</url-pattern>
</servlet-mapping>

[/codesyntax]

http://<host&gt;:<port>/<context-path>/login diyerek LoginServlet isimli sınıfın çağrılması sağlanıyordu.

Action sınıfları için bu sefer struts.xml dosyasında aşağıdaki şekilde bir sabit tanımlanır.

[codesyntax lang=”xml” lines=”no”]

<struts>

  <constant name="struts.action.extension" value="aspx"/> 

  <package name="login" extends="struts-default">
	<action name="login">
		<result>pages/login.jsp</result>
	</action>
  </package>

</struts>

[/codesyntax]

 http://<host>:<port>/<context-path>/login.aspx

Yukarıdaki mapping’de istek tarayıcının adres satırından bir aspx sayfasına yapılıyormuş gibi gözükse de aslında login.jsp sayfası çağrılacaktır. Eğer uzantı hiç istenmiyorsa aşağıdaki tanım yeterli olacaktır.

[codesyntax lang=”xml” lines=”no”]

<struts>

  <constant name="struts.action.extension" value=""/> 

  <package name="login" extends="struts-default">
	<action name="login">
		<result>pages/login.jsp</result>
	</action>
  </package>

</struts>

[/codesyntax]

Bu şekilde bir tanım yapıldığında istek URL’si aşağıdaki gibi olmalıdır.

http://<host&gt;:<port>/<context-path>/login

Eclipse Juno üzerinde Hibernate Örneği

Kullandığım teknolojiler ve araçlar;

  • JDK 1.7
  • Eclipse Juno 4.2
  • Oracle XE 11g
  • Hibernate 4.2

Yazdığım proje basit bir konsol uygulamasıdır. Hibernate’in son sürümü olan 4.2 ile geliştirilmiştir. Dolayısıyla SessionFactory nesnesi yaratılırken deprecate edilen eski metot yerine yenisi kullanılmıştır.

Öncelikle Eclipse’de yeni bir Java projesi yaratalım. Ben ismine HibernateCRUD dedim. Projemin “Build Path” ine Hibernate’in JAR dosyalarını ekliyorum. Bu işlemi proje üzerinde sağ tıklayarak BuildPath -> Add External Archives.. seçeneği ile gerçekleştirebilirsiniz.

1

Kullandığım JAR listesi aşağıdaki gibidir.

  • Öncelikle buradan indirmiş olduğunuz hibernate-search-4.2.0.Final ZIP dosyasını dilediğiniz bir yere çıkartın. Daha sonra distlibrequired  altındaki tüm JAR’ları ekleyin.
  • İkinci adımda eğer benim gibi annotation kullanacaksanız gereken hibernate-annotations.jar, hibernate-commons-annotations.jar, ejb3-persistence.jar dosyalarını ekleyin. Eğer annotation yerine konfigurasyon dosyaları (*.hbm.xml) kullancaksanız o zaman bu JAR’lara gerek yok. Bu JAR’ları şu adresten indirebilirsiniz.
  • Üçüncü adımda hibernate-search-4.2.0.Final dosyası içerisinden distlibprovided dizini altındaki hibernate-jpa-2.0-api-1.0.1.Final.jar dosyasını ekliyoruz.
  • Son olarak da bağlanacağımız veri tabanının driver’ını ekliyoruz. Ben Oracle kullandığım için ojdbc6.jar  dosyasını da CLASSPATH’ime ekliyorum.

Projemin kullandığı kütüphaneler en son aşağıdaki gibi oluyor.

2

 

Veri tabanımızda halihazırda bulunan örnek tablolardan REGIONS tablosunu kullanacağım. Hibernate’in veri tabanına bağlanabilmesi için gerekli olan konfigurasyon dosyasını yaratıyorum. Kaynak kodlarımın bulunduğu yerde yarattığımın hibernate.cfg.xml dosyası aşağıdaki gibi olacaktır. Eğer siz başka bir veri tabanına bağlanıyorsanız bağlantı ayarlarınızı değiştirmelisiniz.

[codesyntax lang=”xml” lines=”no”]

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
		<property name="hibernate.dialect">
			org.hibernate.dialect.OracleDialect
		</property>
		<property name="hibernate.connection.driver_class">
			oracle.jdbc.OracleDriver
		</property>

		<property name="hibernate.connection.url">
			jdbc:oracle:thin:@localhost:1521:xe
		</property>
		<property name="hibernate.connection.username">
			hr
		</property>
		<property name="hibernate.connection.password">
			hr
		</property>

		<!-- List of XML mapping files -->
		<mapping class="com.javauzmani.entities.Regions" />

	</session-factory>
</hibernate-configuration>

[/codesyntax]

Alt yapımızı hazırladıktan sonra şimdi kodu yazmaya başlayalım. Önce veri tabanındaki tabloya karşılık gelen entity sınıfını yaratıyorum.

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.entities;

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

@Entity
public class Regions {

	@Id
	@Column(name = "region_id")
	private int regionId;

	@Column(name = "region_name")
	private String regionName;

	public Regions() {
		super();
	}

	public Regions(int regionId, String regionName) {
		super();
		this.regionId = regionId;
		this.regionName = regionName;
	}

	public int getRegionId() {
		return regionId;
	}

	public void setRegionId(int regionId) {
		this.regionId = regionId;
	}

	public String getRegionName() {
		return regionName;
	}

	public void setRegionName(String regionName) {
		this.regionName = regionName;
	}
}

[/codesyntax]

Daha sonra ekleme, silme, güncelleme ve listeleme işlemlerini yapacak olan sınıfımı yazıyorum.

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.dao;

import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

import com.javauzmani.entities.Regions;

public class RegionsDAO {
	static ServiceRegistry serviceRegistry = null;
	static SessionFactory factory = null;
	static Configuration configuration = null;

	static {
		try {
			configuration = new Configuration().configure("hibernate.cfg.xml");
			serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
			factory = configuration.buildSessionFactory(serviceRegistry);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void addRegions(int regionId, String name) {
		Session session = factory.openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			Regions regions = new Regions(regionId, name);
			session.save(regions);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	@SuppressWarnings("unchecked")
	public List<Regions> listRegions() {
		Session session = factory.openSession();
		Transaction tx = null;
		List<Regions> regions = null;
		try {
			tx = session.beginTransaction();
			regions = session.createQuery("from Regions").list();
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
		} finally {
			session.close();
		}
		return regions;
	}

	public void updateRegions(Integer regionsId, String regionName) {
		Session session = factory.openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			Regions region = (Regions) session.get(Regions.class, regionsId);
			region.setRegionName(regionName);
			session.update(region);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	public void deleteRegions(Integer regionsId) {
		Session session = factory.openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			Regions region = (Regions) session.get(Regions.class, regionsId);
			session.delete(region);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
}

[/codesyntax]

Son olarak da yazmış olduğum DAO sınıfındaki metotları çağıracak örnek bir test sınıfı yaratıyorum.

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.calistir;

import java.util.List;

import com.javauzmani.dao.RegionsDAO;
import com.javauzmani.entities.Regions;

public class CrudDeneme {
	public static void main(String[] args) {

		RegionsDAO dao = new RegionsDAO();
		List<Regions> regions = dao.listRegions();

		for (Regions region : regions) {
			System.out.print("Region Id : " + region.getRegionId());
			System.out.print(", Region Name : " + region.getRegionName());
			System.out.println();
		}
	}
}

[/codesyntax]

[box type=”warning”]Veri tabanı sunucunuzun açık olduğundan emin olunuz !!![/box]

Kodumuzu çalıştırdığımızda çıktı aşağıdaki gibi oluyor.

3

 

Hibernate Mapping Types

Hibernate’te Java sınıflarını veri tabanındaki tablolara eşleştirmek için kullanılan “mapping” dosyalarında tipler karşımıza çıkar. Bu tipler Java tipi ya da SQL tipi değildirler. Bunlar tam olarak Java tiplerini SQL tiplere, SQL tiplerini de Java tiplerine dönüştürmeyi sağlayan Hibernate tipleridir. Örnek bir “mapping” dosyası aşağıdaki gibidir.

Araba.hbm.xml

[codesyntax lang=”xml” lines=”no”]

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
 "-//Hibernate/Hibernate Mapping DTD//EN"
 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name="Araba" table="ARABA">
      <id name="id" type="int" column="id">
         <generator class="native"/>
      </id>
      <property name="marka" column="marka" type="string"/>
      <property name="model" column="model" type="string"/>
      <property name="uretimYili" column="uretim_yili" type="int"/>
   </class>
</hibernate-mapping>

[/codesyntax]

Dönüşümleri sağlayan Hibernate tiplerinin neler olduğu ve hangi dönüşümleri gerçekleştirdiği bilgisinin işinize yarayacağını düşünüyorum.

1 2

serialVersionUID Nedir?

Java kodunuzu yazarken Serializable arayüzünü gerçekleştiren sınıflarınızda derleyicinin uyarı verdiğini görürsünüz. Uyarıyı gidermek istediğinizde de IDE’niz sınıf içerisinde serialVersionUID isminde long tipinde bir değişken yaratır.

Bu değişkeni programımız içerisinde hiçbir zaman kullanmasak da JVM için gereklidir.

Özellikle Java EE uygulamalarında sıkça karşılaştığımız bu değişken sayesinde JVM sınıfımızı daha hızlı bir şekilde byte dizisi haline getirir. Yani daha hızlı Serialize eder.

Serialization yapılan, yapılacak her yerde bu değişken yaratılmalıdır.

Java Message Service – JMS

Her mesajlaşma uygulaması için konfigure edilen iki tip yönetim objesi vardır.
  1. Destinations
  2. Connection Factories
Destinations denilen yapılar mesajları almak, tutmak ve yönlendirmek için kullanılırlar. Queue ve Topic Destination’lar olmak üzere ikiye ayrılırlar.
  1. Queue Destination : Point-to-Point mesajlaşma protokolü
  2. Topic Destination : Yayınla-al mesajlaşma protokolü

İstemci Queue’ya erişebilecek bir Connection sınıfı üzerinden bu Queue’ya erişebilir. Yani direk erişemez. Queue’ya erişmek için bu Connection sınıfını kullanıp session oluşturulur. Session üzerinden Queue’ya bağlanılır. Bu bağlantı sınıfına “connection factory” denir. Connection Factory uygulama sunucusu üzerinde tanımlanır.

İstemci tarafı Queue’ya erişebilsin diye Connection Factory oluşturulur.

Connection factory’ler JMS API Client tarafından JMS API Destination’a bağlanmak için kullanılır. İki kategoriye ayrılırlar.

  1. Queue Connection Factories
  2. Topic Connection Factories

 

İstemcilerin Mesaj Göndermesi :

İstemcileri mesaj gönderen uygulamalar olarak düşünebilirsiniz. Gönderilen mesajlar senkron ya da asenkon olabilir. Yani mesaj gönderildikten sonra cevabın ne zaman döneceği belli olmayabilir. Senkron mesajlarda gönderilen mesajın cevabı beklenir.
1

Mesajlar :

Uygulamaya ait bilgileri sarmalamaya yarayan objelerdir. Mesajın 3 parçası vardır.
  1. Header : Mesajı tanımlamak ve yönlendirmek için bilgi barındırır.
  2. Properties : Mesajları sınıflandırmak için kullanılır. Isim/değer tutulur. Mesajlar özelliklerine göre filtrelenebilir.
  3. Body : Mesajın içeriği bulunur.
5 adet mesaj tipi vardır. Sunucudaki queue ya da topic yapılarına bu beş tipte mesajdan ihtiyaca göre bir tanesi gönderilebilir.
2

 

 

Point-to-point Mesajlaşma (Queue) :

Bir mesaj kuyruğu (queue), mesajların tamamı tükenene kadar saklar. Queue ve topic arasındaki en büyük fark, Queue yapısında tek bir mesaj kullanıcısının olmasıdır. Mesajı gönderen ve alan arasında zaman anlamında bir bağımlılık yoktur. Queue’ya gönderilen tüm mesajlar alıcının yaratılmasından önce bile gönderilmiş olsalar sonradan alınabilirler.
Bir tüketici kuyruktan bir mesajı aldıktan sonra aynı mesaj başka birisi tarafından kullanılamaz.
3

Publish/Subscribe Mesajlaşma (Topic) :

Bir Topic’in birden fazla kullanıcısı olabilir. Mesajı üreten istemci mesajları Topic’e gönderir. Topic mesajların tamamı kullanıcılara dağıtılana kadar hepsini saklar. Burada iki taraf arasında zaman bağımlılığı vardır. Mesaj alacak kişiler, Topic’e kayıt olmadan ya da inaktif durumdayken mesaj alamazlar.
4
EJB bileşenleri (entity, session, message-driven beans) ile mesaj göndermek mümkün olabilir. Yalnız JMS API’nin ihtiyaç duyduğu metotların yazılması gerekir.
Senkron mesaj kullanıcıları sunucuyu bloke edip bağladıkları için session, entity ve message-driven bean’ler ile senkron mesaj göndermek sakıncalıdır.
Message-driven bean’ler MessageListener interface’ini implement ederler. Yani asenkron mesajlaşma için kullanılırlar. MessageListener arayüzünde tanımı yapılmış onMessage() metodunu override ederler. Container’a MessageListener kullanıldığının bir şekilde söylenmesi gerekiyor. Bunu da message-driven bean’lerin başında @MessageDriven annotation‘ı ile ifade ediyoruz.
MDB’lerin local ya da remote interface’leri olmaz. MDB’ler Java EE bileşenleri ile direk olarak haberleşmezler. Önce mesajı queue ya da topic yapısına gönderirler. Container’lar mesajları göndermek için havuz kullanabilirler ki çoğu zaman kullanırlar.
Container MDB instance’ı yaratırken newInstance() adındaki metodu otomatik olarak çağırır. Instance yaratıldıkdan sonra çalışacak olan metot PostConstruct metodudur. (Bu metotları annotationlarla belirliyorduk.) Daha sonra Container beani havuza ekler. Bean daha sonra listener metodunun çağrılmasını bekler. Mesaj eklendikçe listener metodu çalışır.
  • MDB’ler public tanımlanır ve aynı diğer beanler gibi final ya da abstract olmaz.
  • Class tanımının başında @MessageDriven annotation’ı olur.
  • mappedName özelliği ile MDB uygulama sunucusunda tanımlanmış olan destination’lara JNDI ismiyle bağlanır.
  • finallize() metotları olmaz.
  • Bean içerisinde event handler metotları tanımlanabilir. Eskiden bu metotları override etmek zorunluydu şimdi bean instance’ı yaratılmadan önce ve sonra eventler oluşuyor. İstersek PostConstruct ve PreDestroy metotlarını yazabiliyoruz. Aynı diğer bean sınıflarındaki gibi herhangi bir isimde void bir metot tanımlanıyor. Bu metot parametre almıyor. Herhangi bir modifier alabiliyor ama uygulamaya özel exception fırlatmaması gerekiyor. Runtime exception’lar önemli değil. Tanımlarının başına da @PostConstruct ya da @PreDestroy yazıyoruz.
EJB’ler arasındaki haberleşmenin senkron olması gerekli değilse yani cevabını hemen beklemiyorsak asenkron haberleşmeyi kullanıyoruz.  Ne zaman okunacağı bizim için önemli olmadığında MDB kullanıyoruz. Mesajlarımızı bırakıyoruz bir ara okunuyor.

Java Sertifikasyon Sınavları hakkında

Gelen yoğun istek üzerinde sertifikasyon sınavları hakkında basit bilgiler vermek istiyorum. Masaüstü ve web programlama ile ilgili sınavlar aşağıdaki gibi sıralanıyorlar.

Java SE Programlama :

Oracle Certified Associate (OCA) olmak için ;

  • 1Z0-803 kodlu Java SE 7 Programmer I sınavı geçilmelidir. (140 dakika, 90 soru)

Oracle Certified Professional (OCP) olmak için ;

  • OCA sınavı geçilmeli,
  • 1Z0-804 kodlu Java SE Programmer II sınavı geçilmelidir. (150 dakika, 90 soru)

Sınav öncesi alınması önerilen dersler :

Java EE Programlama :

Oracle Certified Professional (OCP) olmak için ;

  • Java SE OCP sınavlarından bir tanesini vermiş olmak gerekir, ayrıca
  • 1Z0-858 kodlu Java Enterprise Edition 5 Web Component Developer Certified Professional sınavı geçilmelidir.  (150 dakika, 69 soru)

Oracle Ceritified Expert (OCE) olmak için ;

  • OCP olmak,
  • 1Z0-899 kodlu Java Enterprise Edition 6 Web Component Developer Certified Expert sınavı geçilmelidir.  (140 dakika, 57 soru)

Sınav öncesi alınması önerilen dersler :

Ders içeriklerine üzerlerine tıklayarak bakabilirsiniz.

Java SE 7u10 piyasaya sürüldü

Aralık 2012’de JDK‘nın güncellenmiş son sürümü piyasaya sürüldü. Bu versiyon ile birlikte şu özellikler eklendi :

  1. Tarayıcıda çalışan bir Java programını devre dışı bırakma yeteneği,
  2. İmzalanmamış applet’ler, Java FX uygulamaları ve Java Web Start için istenen güvenlik seviyesi seçme yeteneği,
  3. JRE güvensiz olduğunu hissettiğinde kullanıcıyı uyarma,
  4. Yeni platformlarda çalışabilme (Windows 8 Desktop Mode1 I,Mac OS 10.8.)

Aşağıdaki adresten Java’nın son sürümünü indirebilirsiniz.

[box type=”download”] Java SE indir[/box]

Metot Ezme (Method Overriding)

Metot aşırı yükleme ve metot ezme sürekli kullanılan ve sıkça karıştırılan kavramlardır. Metot ezme bir sınıftaki metoda, başka bir sınıfta yeni fonksiyonalite eklemeye denir.

Bir metodun ezilebilmesi için ;

  • Metotların birbirinden türeyen sınıflarda bulunması gerekir. (is-a ilişkisi olmalıdır)
  • Metot imzalarının aynı olması gerekir. (bkz. NOT)
  • Metotların dönüş tiplerinin ya aynı ya da ezilen metodun dönüş tipinden türeyen bir tip olması gerekir.
  • Ezilen metodun erişim denetleyicisi ne ise ezen metodun erişim denetleyici de ya aynı ya da daha kapsamlı olmalıdır.
  • Metot bir Exception fırlatıyorsa ezen metot da ya aynı tipte ya da o Exception’dan türeyen başka bir tipte hata fırlatmalıdır.

[box type=”warning”] NOT : Bir metodun ismine, parametre sayısı ve tipinemetot imzası” denir.[/box]

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.overriding;

public class Office {

	protected void kaydet() throws RuntimeException {
		// metot işlemleri
	}
}

[/codesyntax]

 

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.overriding;

public class Word extends Office {

	protected void kaydet() throws RuntimeException {
		// metot işlemleri
	}

/*	protected void kaydet() throws ArrayIndexOutOfBoundsException {
		// metot işlemleri
	}

	public void kaydet() throws RuntimeException {
		// metot işlemleri
	}

*/

}

[/codesyntax]

Office sınıfından türeyen Word sınıfında kaydet metodunu yukarıdaki  gibi birden fazla şekilde ezebiliriz.

Metot Aşırı Yükleme (Method Overloading)

Aynı sınıfta aynı isimde metot tanımlamaya metot aşırı yükleme (overloading) denir. Metot aşırı yüklemenin kuralları vardır.

  • Metotların dönüş tipleri aynı olmalıdır.
  • Metotların isimleri aynı olmalıdır.
  • Metotların aldıkları parametre sayıları eşit ise bu parametrelerden en az birinin tipi farklı olmalıdır. Parametre sayıları farklı olabilir.
  • Metotların aynı sınıfta olması gerekir.

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.overloading;

import java.io.File;

public class DvdOynatici {

	void oynat(File dosya){
		// dosya oynat
	}

	void oynat(String dosyaIsmi){
		// dosya oynat
	}

	void oynat(File dosya, int sure){
		// dosya oynat
	}
}

[/codesyntax]

[box type=”info”] Bir sınıfta birden fazla yapılandırıcı (constructor) varsa buna da “constructor overloading” denir.[/box]

[box] Aynı kurallar varargs metotlar için de geçerlidir.[/box]

JAXB Veri Tipleri

 

XML Schema Type Java Data Type
xsd:string java.lang.String
xsd:integer java.math.BigInteger
xsd:int int
xsd.long long
xsd:short short
xsd:decimal java.math.BigDecimal
xsd:float float
xsd:double double
xsd:boolean boolean
xsd:byte byte
xsd:QName javax.xml.namespace.QName
xsd:dateTime javax.xml.datatype.XMLGregorianCalendar
xsd:base64Binary byte[]
xsd:hexBinary byte[]
xsd:unsignedInt long
xsd:unsignedShort int
xsd:unsignedByte short
xsd:time javax.xml.datatype.XMLGregorianCalendar
xsd:date javax.xml.datatype.XMLGregorianCalendar
xsd:g javax.xml.datatype.XMLGregorianCalendar
xsd:anySimpleType java.lang.Object
xsd:anySimpleType java.lang.String
xsd:duration javax.xml.datatype.Duration
xsd:NOTATION javax.xml.namespace.QName

 

Kaynak : Oracle Docs