Asdfasf

Friday, December 28, 2012

Construct Comma Seperated String from List

Ihtiyac bir cogumuzun muhakkak karsilastigi, bir liste'den icindeki elemanlari bir seperator ile ayiran string olustumak. Benim de yaptigim ve bir cok kod'da karsilastigim hic te hos olmayan bir yontem: Efendim liste null mudur, bos mudur, dolu mudur kontrolu, sonrasinda liste for dongusunde taranir, her bir item'in sonuna seperator eklenir, bir stringBuffer'a append edilir, son item'dan sonra virgul koymamak icin if check'i yapilir falan derken hic te yakisikli olmayan kod ortaya cikar. 

Iyi de Apache Commons bunu bizim icin zaten en guzelinden yapiyor ki

 import java.util.ArrayList;  
 import java.util.List;  
 import org.apache.commons.lang.StringUtils;  
 public class Gunaydin {  
   public static void main(String[] args) {  
     List<String> list = new ArrayList<String>();  
     list.add("ahmet");  
     list.add("mehmet");  
     list.add("mustafa");  
     List<String> list2 = null;  
     // Join all Strings in the Array into a Single String, separated by $#$  
     System.out.println(StringUtils.join(list, "$#$"));  
   }  
 }  


Outputs:

 ahmet$#$mehmet$#$mustafa  

Just for clean codings..

Regular Expressions Reference Guide

Regular expressions really ease to much string operations and validations instead of applying legacy methodologies. Being comfortable in regular expressions depends just practicing :) whenever has a chance to apply. Below is a list of regular expresssion constructs referenced from tutorial on oracle. There are also some examples with really good explanations at mkyong.

 Just for quality coding...

 Character Classes

Construct Description
[abc] a, b, or c (simple class)
[^abc] Any character except a, b, or c (negation)
[a-zA-Z] a through z, or A through Z, inclusive (range)
[a-d[m-p]] a through d, or m through p: [a-dm-p] (union)
[a-z&&[def]] d, e, or f (intersection)
[a-z&&[^bc]] a through z, except for b and c: [ad-z] (subtraction)
[a-z&&[^m-p]] a through z, and not m through p: [a-lq-z] (subtraction)

Negation

To match all characters except those listed, insert the "^" metacharacter at the beginning of the character class. This technique is known as negation.

Ranges

To specify a range, simply insert the "-" metacharacter between the first and last character to be matched, such as [1-5] or [a-h]

Unions

You can also use unions to create a single character class comprised of two or more separate character classes. To create a union, simply nest one class inside the other, such as [0-4[6-8]]. This particular union creates a single character class that matches the numbers 0, 1, 2, 3, 4, 6, 7, and 8.

Intersections

To create a single character class matching only the characters common to all of its nested classes, use &&, as in [0-9&&[345]]. This particular intersection creates a single character class matching only the numbers common to both character classes: 3, 4, and 5.

Subtraction

Finally, you can use subtraction to negate one or more nested character classes, such as [0-9&&[^345]]. This example creates a single character class that matches everything from 0 to 9, except the numbers 3, 4, and 5.

Predefined Character Classes

Construct Description
. Any character (may or may not match line terminators)
\d A digit: [0-9]
\D A non-digit: [^0-9]
\s A whitespace character: [ \t\n\x0B\f\r]
\S A non-whitespace character: [^\s]
\w A word character: [a-zA-Z_0-9]
\W A non-word character: [^\w]

 

Quantifiers

Quantifiers allow you to specify the number of occurrences to match against.

Greedy Reluctant Possessive Meaning
X? X?? X?+ X, once or not at all
X* X*? X*+ X, zero or more times
X+ X+? X++ X, one or more times
X{n} X{n}? X{n}+ X, exactly n times
X{n,} X{n,}? X{n,}+ X, at least n times
X{n,m} X{n,m}? X{n,m}+ X, at least n but not more than m times

Boundary Matchers

Boundary Construct Description
^ The beginning of a line
$ The end of a line
\b A word boundary
\B A non-word boundary
\A The beginning of the input
\G The end of the previous match
\Z The end of the input but for the final terminator, if any
\z The end of the input

Usage of Pattern and Matcher :

java.util.regex.Pattern pattern = Pattern.compile(regex);
java.util.regex.Matcher matcher = pattern.matcher(searchString);

while (matcher.find()) {
                System.out.println(String.format("I found the text"
                        + " \"%s\" starting at "
                        + "index %d and ending at index %d.%n",
                        matcher.group(), matcher.start(), matcher.end());
}

Monday, November 12, 2012

Don’t reinvent the wheel

Use guava libraries for most of utility needs you face while developing.

"Guava project contains several of Google's core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and so forth."

Anti RDBMS

A good article about when and why to use NO-SQL storage systems : http://www.metabrew.com/article/anti-rdbms-a-list-of-distributed-key-value-stores

Check http://www.couchbase.com

Sunday, October 14, 2012

Simple Producer Consumer With LinkedBlockingQueue

Here is a simple Producer/Consumer sample using java.util.concurrent.LinkedBlockingQueue. Simply, Cachiers process tasks waiting in dropbox produced by Producer.

Task class which is processed by Cachier:

 public class Task {  
      private int taskNumber;  
      public Task(int taskNumber) {  
           this.setTaskNumber(taskNumber);  
      }  
      public void setTaskNumber(int taskNumber) {  
           this.taskNumber = taskNumber;  
      }  
      public int getTaskNumber() {  
           return taskNumber;  
      }  
 }  

Dropbox class is the box that tasks are dropped in. This class has LinkedBlockingQueue containing task objects to be processed with max size 20


 import java.util.concurrent.LinkedBlockingQueue;  
 public class Dropbox {  
      LinkedBlockingQueue<Task> blockingQueue = new LinkedBlockingQueue<Task>(20);  
      public Task take() throws InterruptedException {  
           return blockingQueue.take();  
      }  
      public void put(Task t) throws InterruptedException {  
           blockingQueue.put(t);  
      }  
 }  

Producer is responsible from producing tasks and putting them to DropBox. If dropbox reaches its limit, producer thread will be blocked till queue has empty slot


 public class Producer implements Runnable {  
      private Dropbox d;  
      public Producer(Dropbox d) {  
           this.d = d;  
      }  
      @Override  
      public void run() {  
           int i = 0;  
           while (true) {  
                Task t = new Task(i++);                 
                try {  
                     d.put(t);  
                     System.out.println(t.getTaskNumber() + " is added");  
                } catch (InterruptedException e) {  
                     e.printStackTrace();  
                }  
           }  
      }  
 }  

Cachier is consumer and responsible from processing tasks, it waits till dropbox has a task to be processed

 public class Cashier implements Runnable {  
      private Dropbox d;  
      private String name;  
      public Cashier(Dropbox d, String name) {  
           this.d = d;  
           this.name = name;  
      }  
      @Override  
      public void run() {  
           while (true) {  
                try {  
                     Task t = d.take();  
                     System.out.println("Processing " + t.getTaskNumber() + " by "  
                               + name);  
                     Thread.sleep(1000);  
                } catch (InterruptedException e1) {  
                     // TODO Auto-generated catch block  
                     e1.printStackTrace();  
                }  
           }  
      }  
 }  

Here is the main class starting application with 1 producer and 3 consumer

 public class Main {  
      public static void main(String[] args) {  
           Dropbox d = new Dropbox();  
           Producer p = new Producer(d);  
           Cashier c1 = new Cashier(d, "Ahmet");  
           Cashier c2 = new Cashier(d, "Mehmet");  
           Cashier c3 = new Cashier(d, "Fatih");  
           new Thread(c1).start();  
           new Thread(c2).start();  
           new Thread(c3).start();  
           new Thread(p).start();  
      }  
 }  

Friday, October 12, 2012

Scenes From Software Development Life :)




Uploading File with Apache Commons File Upload

To upload file into server and reading uploaded file, we need following apache packages;

http://hc.apache.org/httpcomponents-client-ga/

http://commons.apache.org/fileupload/

Client code is as below, it is just posting a file and string parameter into a servlet:


 import java.io.File;  
 import java.io.IOException;  
 import org.apache.http.HttpResponse;  
 import org.apache.http.client.ClientProtocolException;  
 import org.apache.http.client.HttpClient;  
 import org.apache.http.client.methods.HttpPost;  
 import org.apache.http.entity.mime.MultipartEntity;  
 import org.apache.http.entity.mime.content.FileBody;  
 import org.apache.http.entity.mime.content.StringBody;  
 import org.apache.http.impl.client.DefaultHttpClient;  
 public class UploadFile {  
   public static void main(String[] args) throws ClientProtocolException, IOException {  
     HttpClient client = new DefaultHttpClient();  
     String url = "http://127.0.0.1:8080/servlet";  
     HttpPost post = new HttpPost(url);  
     File file = new File("c:\\sil\\SID.jpg");  
     MultipartEntity entity = new MultipartEntity();  
     entity.addPart("file", new FileBody(file));  
     entity.addPart("parameter", new StringBody("value"));      
     post.setEntity(entity);  
     HttpResponse response = client.execute(post);  
     System.out.println(response);  
   }  
 }  

How uploaded file and http parameter can be processed in servlet side?

  public SmsForm processRequest(HttpServletRequest request) throws IOException, ServletException {  
     String contentType = request.getContentType();      
     SmsForm smsForm = new SmsForm();          
     if ((contentType != null) && (contentType.startsWith("multipart/form-data"))) {  
       DiskFileUpload fu = new DiskFileUpload();  
       fu.setSizeMax(100000);  
       fu.setSizeThreshold(4096);  
       fu.setRepositoryPath(System.getProperty("java.io.tmpdir"));  
       try {  
         List fileItems = fu.parseRequest(request);  
         Iterator iter = fileItems.iterator();  
         while (iter.hasNext()) {  
           FileItem item = (FileItem) iter.next();  
           String fileName = item.getName();  
           if (item.getName() == null) {  
             String fieldName = item.getFieldName();              
             smsForm.setField(fieldName, item.getString());              
           } else {  
             smsForm.setFile(item);  
           }  
         }  
       } catch (Exception e) {  
         e.printStackTrace();  
       }        
     }   
   }  

Placing Build Details into MANIFEST.MF via ANT / Maven

If it is needed to place build details into MANIFEST.MF file under META-INF directory of jar file, that can be accomplished via ANT in build.xml as below

      <tstamp>  
           <format property="TODAY" pattern="yyyy-MM-dd HH:mm:ss" />  
      </tstamp>  
      <target name="build" depends="compile">  
           <war warfile="${dist.home}\${dist.war}" basedir="${deploy.home}" webxml="${deploy.home}\WEB-INF\web.xml" excludes="javadoc">  
             <manifest>               
              <attribute name="Built-By" value="${user.name}"/>            
                 <attribute name="Built-Date" value="${TODAY}" />       
              <attribute name="Implementation-Vendor" value="XXXX"/>  
              <attribute name="Implementation-Title" value="${app.name}"/>  
              <attribute name="Implementation-Version" value="${release.number}"/>               
             </manifest>  
           </war>  
      </target>  

Just put required attributes between manifest tag of war or jar task. Output of MANIFEST.MF file would be as below:

 Manifest-Version: 1.0  
 Ant-Version: Apache Ant 1.7.1  
 Created-By: 14.2-b01 (Sun Microsystems Inc.)  
 Built-By: fkul  
 Built-Date: 2012-10-12 17:18:20  
 Implementation-Vendor: XXXX  
 Implementation-Title: product  
 Implementation-Version: 01_01_00_Build01  



Additionally, how those attributes in MANIFEST.MF can be read? As below:

   public static String getBuildDetails() throws MalformedURLException, IOException {  
     Class clazz = ThisClass.class;  
     String className = clazz.getSimpleName() + ".class";  
     String classPath = clazz.getResource(className).toString();  
     if (!classPath.startsWith("jar")) {  
       // Class not from JAR  
       return null;  
     }  
     System.out.println("ClassPath=" + classPath);  
     String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";  
     System.out.println("ManifestPath=" + manifestPath);  
     Manifest manifest = new Manifest(new URL(manifestPath).openStream());  
     Attributes attr = manifest.getMainAttributes();  
     return attr.getValue("Implementation-Title") + " : " + attr.getValue("Implementation-Version");  
   }  

By shipping build details in MANIFEST.MF and reading them on runtime is a good idea to inform user of product on runtime as which version of product is currently running.

In Maven

If you are using maven, that can be accomplished in pom as below:

<properties>
     <maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>
</properties>

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-war-plugin</artifactId>
 <version>2.3</version>
 <configuration>
   <archive>
  <manifest>
    <addClasspath>true</addClasspath>
  </manifest>
  <manifestEntries>            
   <Built-Date>${maven.build.timestamp}</Built-Date>            
   <Implementation-Vendor>${vendor}</Implementation-Vendor>
   <Implementation-Title>${name}</Implementation-Title>
   <Implementation-Version>${version}</Implementation-Version>
  </manifestEntries>
   </archive>
 </configuration>
</plugin>

Monday, October 08, 2012

Oracle SID vs SERVICE_NAME

If you connect to ORACLE with SERVICE_NAME, you should define it as below


MADDB=
  (DESCRIPTION=
    (ADDRESS=
      (PROTOCOL=TCP)
      (HOST=172.28.106.152)
      (PORT=1552)
    )
    (CONNECT_DATA=
      (SERVICE_NAME=MADDB)
    )
  )

If you work with SID, you can define it at TOAD by clicking on checkbox while defining TNS name


which will be as below


MADDB=
  (DESCRIPTION=
    (ADDRESS=
      (PROTOCOL=TCP)
      (HOST=172.28.106.152)
      (PORT=1552)
    )
    (CONNECT_DATA=
      (SID=MADDB)
    )
  )


What about connection URL?

To connect with SERVICE_NAME:

jdbc:oracle:thin:@172.28.106.152:1552/MADDB

To connect with SID:

jdbc:oracle:thin:@172.28.106.152:1552:MADDB

For details : http://www.rojotek.com/blog/2008/01/04/oracle-sid-service_name/

Wednesday, October 03, 2012

Shipping WSDL with Jar for JAX-WS Client

If you work with JAX-WS for webservice client, jax-ws needs wsdl file on runtime. For this purpose, it is better to ship wsdl file with your client code in jar file. Just put wsdl file at top level directory in jar file as below:
-JAR
----META-INF/
----wsdl/service.wsdl

Then, you can instantiate client port as below


 URL wsdlLocation = MyClass.class.getResource("/wsdl/service.wsdl");  
 MyService service = new MyService(wsdlLocation);  
 MyPort proxy = service.getBasicHttpBindingPort();  
 ((BindingProvider) proxy).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, serviceEndPointUrl);  

.

Thursday, September 20, 2012

Blogger Code Formatter

Blog'da yayinladigimiz kaynak kodlari formatlamak icin oldukca kullanisli bir formatter:

http://hilite.me/

Yakisikli kod'lar dilegiyle.

Pooling and Reusing JAX-WS Client Ports


Load test'leri icin hazirladigim bir simulator uygulamasinda, load altinda kisa bir sure sonra uygulamadan server'a yapilan webservice isteklerinde gecikmeler farkettik. Simulator uygulamasi, apache tomcat'da calisan bir web uygulamasi ve webservis istekleri icin jax-ws ile urettigimiz client kod'u kullaniyor.
Cagri yapan kod asagidaki gibi, her istek oncesinde servis ve port yaratip istekte bulunuyor


 public void callServer(){  
      XXXService service = new XXXService();  
      XXXServicePortType port = service.getXXXServiceHttpSoap11Endpoint();  
      WsUtil.setEndpointAdress(port, TestManager.SERVER_URL);  
      Response response = null;  
      try {  
           response = port.callServer();  
      } catch (SOAPFaultException e) {  
      }  
 }  
 public static void setEndpointAdress(final Object port, final String newAddress) {  
     final BindingProvider bp = (BindingProvider) port;  
     bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, newAddress);  
 }  

Sorunun nedenini bulmak, gecikme ve beklemelerin neden kaynaklandigini anlamak icin simulator uygulamasinin thread dump'ini inceledim.

 jstack <process Id>  

thread dump'in soyledigi, thread'lerin yeni servis objesi yaratirken, WSDL definition'ini yuklerken bekledikleri


 "pool-1-thread-400" prio=3 tid=0x0000000002101800 nid=0x215 waiting for monitor entry [0xfffffd7ff2c35000]  
   java.lang.Thread.State: BLOCKED (on object monitor)  
     at org.apache.axis2.jaxws.ClientConfigurationFactory.getClientConfigurationContext(ClientConfigurationFactory.java:88)  
     - waiting to lock <0xfffffd7f8626c060> (a org.apache.axis2.jaxws.ClientConfigurationFactory)  
     at org.apache.axis2.jaxws.description.impl.DescriptionFactoryImpl.createServiceDescription(DescriptionFactoryImpl.java:92)  
     at org.apache.axis2.jaxws.description.impl.DescriptionFactoryImpl.createServiceDescription(DescriptionFactoryImpl.java:79)  
     at org.apache.axis2.jaxws.description.DescriptionFactory.createServiceDescription(DescriptionFactory.java:76)  
     at org.apache.axis2.jaxws.spi.ServiceDelegate.<init>(ServiceDelegate.java:212)  
     at org.apache.axis2.jaxws.spi.Provider.createServiceDelegate(Provider.java:59)  
     at javax.xml.ws.Service.<init>(Service.java:56)  
     at com.xxx.xxx.xxx.XXXService.<init>(XXXService.java:47)  


Kisaca, her webservice istegi oncesi yeni servis ve port objesi olusturup, WSDL definition'ini yukletmek ve yuklerken alt tarafta kuvvetle muhtemel syncronized bir block'ta zaman kaybetmek pekte mantikli degil.

Pooling bir cozum olacaktir.

Uygulama ayaga kalkarken, kullanacagimiz port'lari ihtiyacimiz kadar yaratip bir queue'da tutmak ve bu havuzdan kullanmak, kullandiktan sonra queue'ya baskalarinin kullanmasi icin koymak uygun olacaktir.


 static BlockingQueue<XXXServicePortType> portQueue = new LinkedBlockingQueue<XXXServicePortType>();  
 public static void initialize() {  
      try {  
           long start = System.currentTimeMillis();  
           int portCount = Integer.parseInt(TestManager.PORT_POOL_COUNT.trim());  
           for (int i = 0; i < portCount; i++) {  
                XXXService service = new XXXService();  
                XXXServicePortType port = service.getXXXServiceHttpSoap11Endpoint();  
                WsUtil.setEndpointAdress(port, TestManager.SERVER_URL);  
                try {  
                     portQueue.put(port);  
                } catch (InterruptedException e) {  
                     e.printStackTrace();  
                }  
           }  
           TestManager.debug("Producing ports took " + (System.currentTimeMillis() - start));  
      } catch (Exception e) {  
           TestManager.error("", e);  
      }  
 }  
 public void callServer(){  
      XXXServicePortType port = null;  
      Response response = null;  
      try {  
           long l = System.currentTimeMillis();  
           port = portQueue.take();        
           TestManager.debug("Taking port took:[" + (System.currentTimeMillis() - l) + " msec");                 
           response = port.callServer();  
      } catch (InterruptedException e) {  
           e.printStackTrace();  
      } finally{  
           if (port != null){  
                try {  
                     portQueue.put(port);  
                } catch (InterruptedException e) {  
                     e.printStackTrace();  
                }  
           }  
      }  
 }  


Pooling bize gozle gorulur, ciddi bir iyilesme kazandirdi. Ek olarak her bir port ve kullandigi fiziksel connection arasindaki iliskiden bahsetmek gerekirse:

netstat -n komutu ile load sirasinda server'a kurulan fiziksel baglanti'lari inceledigimde sunu gordum. Pool kullandigimizda, cagrilan url ayni oldugu durumda, port sayisinca connection yaratildigini ve operating system tarafindan canli tutuldugunu gordum. Havuzdaki client port objeleri, canli tutulan bu fiziksel http connection'larini her seferinde kullaniyorlar.

Cagrilan url'i anlik olarak degistirdigim durumda ise operating system yeni bir connection yaratiyor ve port objesi bu yeni connection uzerinden http call yapiyor. Bir sekilde fiziksel connection yonetimi operating system tarafindan yapiliyor ve kisaca port objesinin o anda cagiracagi ip:port icin hazirda bir http connection var ise o kullaniliyor, yok ise yaratiliyor.

SONUC OLARAK:

Webservice cagrisinda asil maliyetli olan service ve port objelerini her seferinde yaratip servis tanimini (WSDL dosyasini) yukletmek oldugunu gorduk, ve bunun yerine port objelerini ayaga kalkarken yaratip bir havuzda tutup tekrar tekrar kullanmak cozumunu uyguladik.

Fiziksel http connection yonetimi ise alt tarafta bir sekilde handle ediliyor ve dikkate deger bir maliyeti olmadigini soyleyebilirim.

Monday, September 17, 2012

Managing cache with Ehcache

IHTIYAC:

 Uretmesi ve elde etmesi maliyetli olan entity'leri olasi sonradan ihtiyaclarda tekrardan uretmek yerine memory'de tutuyoruz, Bunu basitce entity'leri bir ConcurrentHashMap'de tutup, ihtiyac duydugumuz anda da ulasarak sagliyabiliriz. Ancak outOfMemory almamak icin map'de tuttugumuz bu objelerin belli bir sure sonra expire olmalarini saglamali, hatta Map'de tuttugumuz objelerin sayisini da limitli tutmamiz lazim. Bunun icin belli araliklarda calisan bir TimerTask'imiz var, ve Map'deki entity'leri tarayarak, suresi gecmis entity'leri Map'den temizliyoruz.

Butun bu isi kendimiz manage etmek yerine bunu bizim icin belki de daha optimize yapan bir urun var ehcache.

 Ufak bir test kod'u ile kullanimina bakalim. TTL degerimiz 2 sn, yani cach'e koydugumuz obje 2 sn sonra expire olmali ve cache en fazla 100 eleman bulundurmali, eleman sayisi bunu artarsa, first in first out mantigi ile eski elaman'lar cache'den atilip yerine yenileri konmali:

Dependency'lerimiz:

 <dependencies>  
   <dependency>  
    <groupId>junit</groupId>  
    <artifactId>junit</artifactId>  
    <version>4.7</version>  
    <scope>test</scope>  
   </dependency>  
   <dependency>  
       <groupId>net.sf.ehcache</groupId>  
       <artifactId>ehcache</artifactId>  
       <version>2.0.0</version>  
       <type>pom</type>  
      </dependency>  
      <dependency>  
           <groupId>org.slf4j</groupId>  
           <artifactId>slf4j-log4j12</artifactId>  
           <version>1.5.6</version>  
      </dependency>  
 </dependencies>  

Test Code'u:

 import net.sf.ehcache.Cache;  
 import net.sf.ehcache.CacheManager;  
 import net.sf.ehcache.Element;  
 import net.sf.ehcache.config.CacheConfiguration;  
 import org.junit.Before;  
 import org.junit.Test;  
 /**  
  * Unit test for simple App.  
  */  
 public class AppTest  
 {  
   public static final int TTL_IN_SEC = 2;  
   public static final int MAX_ELEMENT_IN_MEMORY = 100;  
   static {  
     CacheManager manager = CacheManager.create();  
     //Create a Cache specifying its configuration.  
     Cache cache = new Cache(new CacheConfiguration("myCache", 1000).timeToLiveSeconds(TTL_IN_SEC).maxElementsInMemory(100));  
     manager.addCache(cache);  
   }  
   @Before  
   public void init() throws Exception {  
     Cache cache = CacheManager.getInstance().getCache("myCache");  
     Element e = new Element(1, "test");  
     cache.put(e);  
   }  
   @Test  
   public void shouldRemoveAfterTTL() throws Exception {  
     Cache cache = CacheManager.getInstance().getCache("myCache");  
     Element e = cache.get(1);  
     org.junit.Assert.assertEquals(e.getValue(), "test");  
     System.out.println("hit value by 1 = " + e);  
     System.out.println("sleep by TTL + 1 sec ");  
     Thread.sleep(TTL_IN_SEC * 1000 + 1000);  
     e = cache.get(1);  
     org.junit.Assert.assertNull(e);  
     System.out.println("hit value by 1 = " + e);  
   }  
   @Test  
   public void shouldRemoveFirstElementWhenCacheFull() throws Exception {  
     Cache cache = CacheManager.getInstance().getCache("myCache");  
     Element e = cache.get(1);  
     System.out.println("hit value by 1 = " + e);  
     org.junit.Assert.assertEquals(e.getValue(), "test");  
     for (int i = 2; i &lt;= 2 * MAX_ELEMENT_IN_MEMORY; i++) {  
       e = new Element(i, "test" + i);  
       cache.put(e);  
     }  
     e = cache.get(1);  
     org.junit.Assert.assertNull(e);  
     System.out.println("xxhit value by 1 = " + e);  
   }  
 }  

Hizli ve optimize yazilimlar dilegiyle.

Thursday, September 06, 2012

Throttling with RabbitMQ

Broadcasting with Hazelcast


Farkli host'larda clustered calisan uygulamalarimizin birbirleri ile haberlesmelerine ihtiyacimiz var. Host'lardan birinde gerceklesen bir event'in diger hostlar tarafindan haberdar edilmesi lazim. Bu amacla ve daha bir cok ozelligi ile (distributed caching, load balancing, publish/subscriber messaging) ve en onemlisi kullanim basitligi ile Hazelcast kullanabiliriz.

Asagida Hazelcast kullanarak bir broadcasting ornegi yapalim.

Dependency'miz

 <dependency>  
      <groupId>com.hazelcast</groupId>  
      <artifactId>hazelcast</artifactId>  
      <version>2.2</version>  
 </dependency>  

Hazelcast servisimizi ayaga kaldiralim:

    import org.apache.log4j.Logger;   
    import com.hazelcast.config.Config;   
    import com.hazelcast.config.Join;   
    import com.hazelcast.config.NetworkConfig;   
    import com.hazelcast.core.Hazelcast;   
    import com.hazelcast.core.HazelcastInstance;   
    import com.hazelcast.core.MultiTask;   

    public class HazelcastService{  

    public static Logger    logger = Logger.getLogger(HazelcastService.class);   
    private static HazelcastInstance hazelcastInstance;   
    private static boolean   initialized = false;   

    public void deploy() {   
    logger.info("INITIALIZING HAZELCAST......");   
    try {   
     System.setProperty("hazelcast.logging.class",    HazelcastLoggerFactory.class.getName());    
     Config cfg = new Config();   
     cfg.setPort(ServiceProperties.HAZELCAST_PORT);   
     cfg.setPortAutoIncrement(true);   
     NetworkConfig network = cfg.getNetworkConfig();   
     Join join = network.getJoin();   
     join.getMulticastConfig().setEnabled(false);   
     String ips = ServiceProperties.HAZELCAST_CLUSTER_HOST_IPS_SEPERATED_BY_COMMA;   
     StringTokenizer tok = new StringTokenizer(ips, ",");   
     while (tok.hasMoreTokens()) {   
      join.getTcpIpConfig().addMember(tok.nextToken());   
     }   
     join.getTcpIpConfig().setEnabled(true);   
     hazelcastInstance = Hazelcast.newHazelcastInstance(cfg);   
     initialized = true;   
    } catch (Exception e) {   
     logger.error(e);   
    }   
    logger.info("INITIALIZED HAZELCAST......");   
   }   
 }  

Mesaj gonderimini tetikleyelim:

 public static void notifyEvent(String eventId) {  
     if (!initialized) {  
       logger.warn("HazelcastService is not initialized, doint nothing");  
       return;  
     }  
     try {  
       Event event = new Event(eventId);  
       MultiTask<Boolean> task = new MultiTask<Boolean>(event, hazelcastInstance.getCluster().getMembers());        
       broadcast(task);  
     } catch (Exception e) {  
       logger.error(e);  
     }  
   }  
      private static void broadcast(MultiTask<Boolean> task) throws InterruptedException, ExecutionException, TimeoutException {  
     ExecutorService executorService = hazelcastInstance.getExecutorService();  
     executorService.execute(task);  
     Collection<Boolean> results = task.get(3, TimeUnit.SECONDS);  
     logger.info("Call Results: " + Arrays.toString(results.toArray()));  
   }  

Diger hostlarda mesaj'i karsilayacak class'imiz

 public class Event implements Callable<Boolean>, Serializable {  
   protected String eventId;  
   public PricePlanUpdated(eventId) {  
     super();  
     this.eventId = eventId;      
   }  
   public Boolean call() {  
     try {  
       HazelcastService.logger.info("Received event message with eventId:" + eventId);  
       //do job  
       HazelcastService.logger.info("Processed event message with eventId:" + eventId);  
     } catch (Exception e) {  
       HazelcastService.logger.error(e);  
     }  
     return true;  
   }    
 }  

That's all.

Wednesday, August 15, 2012

Oracle'da Tablo uzerinde LOCK kullanimi

Bugunumden DB ogrenilerim asagidaki gibi.

1.) Ayni tablo uzerinde sadece 1 instance'in o anda calismasini garanti etmek istiyor isek tablo ustunde lock'lamayi SELECT FOR UPDATE komutu ile asagidaki sekilde yapabiliriz.



SELECT * FROM TABLE FOR UPDATE 

Bu komut sonrasinda, o session disinda baska session'dan bu tabloya yapilan istekler, lock'i alan connection'inin commit ya da rollback cagirmasina kadar bekleyeceklerdir. Lock'i alan session, bu sure boyunca bu tabloda istedigi select/update/delete islemlerini gerceklestirebilecektir.

2.) Peki tablolar uzerinde lock'lari nasil goruyor ve kaldiriyoruz:

 select oracle_username,object_id,session_id from v$locked_object

ilgili session'in serial numarasini aliyoruz:

 select sid,serial# from v$session where sid=<session_id>;

ve session'i oldurup manueal olarak lock'i kaldirma icin:

 alter system kill session '<sId>,<serial#>';

3.) Tablodaki ilk n kaydi almak icin ise:

SELECT * FROM TABLE where ROWNUM <= n

Saturday, August 11, 2012

Eclipse'de Mavenized Web Projesi Olusturmak

Asagidaki adimlar izlenir
1.) Eclipse'de New Maven Project with archtpe maven-archetype-webapp
2.) Dependency'ler pom.xml'e girilir.
3.) Maven dependency'lerinin eclipse classpath'ine eklenmesi icin mvn eclipse:eclipse calistirilir.
4.) Eclipse projesi refresh edilir.
5.) WTP (Web Tools Platform) yuklu oldugundan emin olun
Help ->Install menusunden http://download.eclipse.org/webtools/repository/helios repository'sinden yuklenebilir.
6.) Bu projeyi dynamic web project haline ceviren sihirli komut: mvn eclipse:eclipse -Dwtpversion=2.0
7.) Bu asamada proje Eclipse embedded Tomcat ustunde calisir hale gelmistir. Tomcat, projeyi yuklerken maven dependency'lerini goremiyor ise son care olarak:
8.) Proje uzerinden Properties -> Deployment Assembly -> Add -> Java Build Path Entries -> burdaki listeden maven dependency'leri secilerek Tomcat classpath'ine eklenmesi saglanir.

Sunday, July 15, 2012

Logging & LogBack & Slf4j

Loglamanin, bir yazilim projesi icin ne kadar onemli oldugunu biliyoruz. Yapilan arastirmalar, bir projesinin, %4'luk kisminin loglama'ya ayrildigini gosteriyor ki hacim olarak hic de azimsanmayacak bir deger.

Bir loglama framework'u olarak LogBack urununun kullanimini paylasacagim, Ceki Gulcu tarafindan gelistirilmis ve slf4j'nin kiz kardesi. Slf4j, loglama framework'unden bagimsiz olarak kodumuzu gelistirmemizi saglayan bir onyuz (facade) saglarken, logback, bizatihi loglama framework'unun kendisi.

Slf4j 'yi daha iyi ifade eden yine kendi sitesinden : The Simple Logging Facade for Java or (SLF4J) serves as a simple facade or abstraction for various logging frameworks, e.g. java.util.logging, log4j and logback, allowing the end user to plug in the desired logging framework at deployment time:

Hemen uygulamaya gecelim. Eclipse'de maven projemizi olusturuyoruz. Pom.xml'e girecegimiz dependency'ler su sekilde: 
<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.6</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.0.6</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-access</artifactId>
        <version>1.0.6</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.6.6</version>
    </dependency>            
  </dependencies>

logback.xml'imizi hazirliyoruz. LogBack'in configurasyon dosyasini bulabilmesi icin, logback.xml'in classpath'de olmasi gerekiyor.

Maven der ki, configurasyon dosyalarinizi src->main->config altina koyun ki biz de oyle yapiyoruz.

<configuration debug="true" scan="true" scanPeriod="10 seconds" >

    
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile.log</file>
    <append>true</append>
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
  
  
  
</configuration>


Peki eclipse logback.xml'i nasil classpath'e ekleyecek? Java Build Path -> Libraries -> Add External Class Folder:

En basit bir HelloWorld uygulamasi su sekilde:

package com.ferhat.logback_work;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld1 {

    static Logger logger = LoggerFactory.getLogger(HelloWorld1.class);

    public static void main(String[] args) {
        logger.debug("Hello world. {}", getString());
    }

    public static String getString() {
        return "ferhat";
    }
}

Dikkat ederseniz, kod icinde direk logBack dependency'si yok, slf4j hangi logging framework'u kullanacagini, classpath'imizde bulacagi logging framework'une gore karar veriyor ki biz logback jar'larini classpath'imizde bulunduruyoruz.

Logback kullanimi ile alakali detaylari burdan bulabilirsiniz.

logback.xml'deki bir-iki ufak detay dan bahsedeyim
<configuration debug="true" scan="true" scanPeriod="10 seconds" >

1.)debug="true" oldugu durumda, uygulamamiz baslarken logback, sistemde buldugu configurasyon dosyalari ve varsa hatalar hakkinda log basiyor ki faydali olacaktir.


2.)scan="true" oldugu durumda, logback belli araliklarla (scanPeriod="10 seconds"), logback.xml dosyasina goz atip var ise degisiklikleri uyguluyor.

3.)Log metodunun cagrildigi satir numarasini yazdirmak icin [%file:%line] ekliyoruz ancak runtime'da satir numarasi bilgisine ulasmanin maliyetli bir is oldugunu eklemekte fayda var:
<pattern>%-4relative [%thread] %-5level %logger{35} [%file:%line] - %msg%n</pattern>


Eclipse'de Maven Projesi Olusturma

Maven, standard bir maven projesinde, dosya yapisinin su sekilde olusturulmasini oneriyor:

src/main/javaApplication/Library sources
src/main/resourcesApplication/Library resources
src/main/filtersResource filter files
src/main/assemblyAssembly descriptors
src/main/configConfiguration files
src/main/scriptsApplication/Library scripts
src/main/webappWeb application sources
src/test/javaTest sources
src/test/resourcesTest resources
src/test/filtersTest resource filter files
src/siteSite
LICENSE.txtProject's license
NOTICE.txtNotices and attributions required by libraries that the project depends on
README.txtProject's readme

Bu yapiyi, Eclipse'de manuel olarak olusturabilecegimiz gibi, daha bircok avantaji ile beraber, m2e plugin'i sayesinde olusturabiliriz.

Eclipse'de Help->Eclipse Marketplace adimindan  Maven Integration for Eclipse kurulumunu yapalim.






Kurulum sonrasi, mavenized bir projeyi, New -> Maven Project adimi ile olusturabiliriz:

m2e, bizim icin standart bir maven projesi olusturuyor ve proje uzerinde kosabilecegimiz maven komutlarini, proje uzerine sag tiklayip Run menusunden sagliyor:

eclipse:eclipse

Proje dependency'lerimizi pom.xml'e girdikten sonra, bu dependency'lerin local repository'mize indirilip, projenin buildpath'ine eklenmesi icin eclipse:eclipse goal'unu kullanabiliriz. Peki local repository'miz neresi ve eclipse build path'e dependency'leri nasil ekliyor?
Eclipse'de, Project -> Preferences->Maven->User Settings' de maven kurulum ve settings.xml bilgisini gorebiliriz. Local repository bilgisi, settings.xml icinde mevcuttur.


Local repository bilgisini, Eclipse'e M2_REPO degiskeni olarak tanimliyoruz:
Project->Preferences -> Java->Build Path-> Class Path Variables -> New :
Proje uzerinde eclipse:eclipse goal'unu kostuktan sonra, projemizi refresh edince, dependency'lerin build path'imize eklendigini gorecegiz.

Friday, July 13, 2012

Simple JAX-WS WebService

Tomcat, WAR, AXIS ile ugrasmadan, JAX-WS ile standalone bir webservice ayaga kaldirmak bu kadar kolay:
Orjinali http://www.mkyong.com/webservices/jax-ws/jax-ws-hello-world-example/ da olan ornegi baz alip, sadece input parametrelerine Enum ve ArrayList ekleyip, annotation lar ile ornegi biraz daha zenginlestirmeye calistim.
JAX-WS annotation'larinin kullanimi icin :http://jax-ws.java.net/jax-ws-ea3/docs/annotations.html

Ilk adimimiz, acacagimiz servis'in interface'i

package com.mkyong.ws;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

//Service Endpoint Interface
@WebService
@SOAPBinding(style = Style.RPC)
public interface HelloWorld {

    @WebMethod
    String getHelloWorldAsString(@WebParam(name = "request") Request request);

}


Metodumuz Request objesi aliyor ki icerigi su sekilde:

package com.mkyong.ws;

import java.util.ArrayList;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;

public class Request {
    private String name;
    private CallType callType;
    private ArrayList<String> clients;

    public String getName() {
        return name;
    }

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

    public CallType getCallType() {
        return callType;
    }

    public void setCallType(CallType callType) {
        this.callType = callType;
    }

    @XmlElementWrapper(name = "clients")
    @XmlElement(name = "client")
    public ArrayList<String> getClients() {
        return clients;
    }

    public void setClients(ArrayList<String> clients) {
        this.clients = clients;
    }

}


package com.mkyong.ws;

public enum CallType {
    TEST, PROD;
}


WebService interface'imizi implemente ediyoruz:

package com.mkyong.ws;

import javax.jws.WebService;

//Service Implementation
@WebService(endpointInterface = "com.mkyong.ws.HelloWorld")
public class HelloWorldImpl implements HelloWorld {

    @Override
    public String getHelloWorldAsString(Request request) {
        System.out.println(request.getClients().size());
        return "Hello World JAX-WS " + request.getName() + ", "
                + request.getCallType() + ", " + request.getClients().get(0);
    }
}

Ve en can alici nokta: Kodladigimiz buservisi tek satirda publish ediyoruz:

package com.mkyong.endpoint;

import javax.xml.ws.Endpoint;

import com.mkyong.ws.HelloWorldImpl;

//Endpoint publisher
public class HelloWorldPublisher {

    public static void main(String[] args) {
        Endpoint.publish("http://localhost:9999/ws/hello", new HelloWorldImpl());
    }

}

WSDL'den wsimport ile client code uretip kullanmanin detaylari mkyong da mevcut, sadece HelloWorld interface'i elimizde mevcut ise client kod'u su sekilde olusturup kullanmamiz mumkun:


package com.mkyong.client;

import java.net.URL;
import java.util.ArrayList;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import com.mkyong.ws.CallType;
import com.mkyong.ws.HelloWorld;
import com.mkyong.ws.Request;

public class HelloWorldClient {

    public static void main(String[] args) throws Exception {

        URL url = new URL("http://localhost:9999/ws/hello?wsdl");

        // 1st argument service URI, refer to wsdl document above
        // 2nd argument is service name, refer to wsdl document above
        QName qname = new QName("http://ws.mkyong.com/",
                "HelloWorldImplService");

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

        HelloWorld hello = service.getPort(HelloWorld.class);

        ArrayList<String> clients = new ArrayList<String>();
        clients.add("c1");

        Request request = new Request();
        request.setName("ferhat");
        request.setCallType(CallType.TEST);
        request.setClients(clients);

        System.out.println(hello.getHelloWorldAsString(request));

    }
}

Throttling


Cozmemiz gereken problem su, uygulamamiz belli bir interval'da belli sayida istegi kabul etmeli, bunun disindakileri reject etmeli. Yani sistemin TPS degerini garanti ettigimiz bir seviyede tutmak.

Bu problemin cozumu icin internette arastirirken, sagolsun Microsoft'dan Sergey abimizin cozumune rastladim. thanks Sergey, I owe a lot to you (http://1-800-magic.blogspot.com/)

Asagida Sergey'in Throttling mekanizmasini, thread pool ile bereaber kullanmaya calistim,
Talepleri, 10 TPS ile sinirlandirip, bu talepleri de 20'lik bir BlockingQueue icinden thread pool kullanarak eritelim.
  •  Max 10 TPS calisiyor  
RequestThrottler throttler = new RequestThrottler(10, 1000);
  • Talepleri 20'lik bir queue icinden eritiyoruz
new ArrayBlockingQueue(20);
  • Her talebin islenmesi 2 sn suruyor.

System.out.println("Executing index:" + index + " by "
                    + Thread.currentThread().getName());
            Thread.sleep(2000);

Test class'imiz asagidaki gibi:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Test implements Runnable {
    int index;

    @Override
    public void run() {
        try {
            System.out.println("Executing index:" + index + " by "
                    + Thread.currentThread().getName());
            Thread.sleep(2000);
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 10 trx per second
        RequestThrottler throttler = new RequestThrottler(10, 1000);

        TestRejectedExecutionHandler execHandler = new TestRejectedExecutionHandler();

        BlockingQueue q = new ArrayBlockingQueue(20);
        ThreadPoolExecutor ex = new ThreadPoolExecutor(4, 10, 20,
                TimeUnit.SECONDS, q);
        ex.setRejectedExecutionHandler(execHandler);

        for (int i = 0; i < 10000; i++) {

            Thread.sleep(20);

            if (throttler.tryStartRequest() == 0) {
                System.out.println("Request Accepted " + i + " "
                        + System.currentTimeMillis());
                Test test = new Test();
                test.index = i;
                ex.execute(test);
            } else {
                System.err.println("Request Rejected by Throttler " + i);
            }
        }
    }
}

class TestRejectedExecutionHandler implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable arg0, ThreadPoolExecutor arg1) {
        Test test = (Test) arg0;
        System.out.println(test.index + " is rejected");
    }
} 

Asagida RequestThrottler'in code'u mevcut. Orjinali icin: http://1-800-magic.blogspot.com/2008/02/throttling-requests-java.html

Genel hatlari ile yaptigi, her bir request'i, talep zamanlari ile indexleyip
long[] _ticks
, ilk ve son talebin _interval araliginde ve _maxCalls adedini gecmemesini kontrol etmek, bu sureci her interval'da resetleyip tekrar etmek:

/**
 * Class that throttles requests. Ensures that the StartRequest cannot be called
 * more than a given amount of time in any given interval.
 * 
 * StartRequest blocks until this requirement is satisfied.
 * 
 * TryStartRequest returns 0 if the request was cleared, or a non-0 number of
 * millisecond to sleep before the next attempt.
 * 
 * Simple usage, 10 requests per second:
 * 
 * Throttler t = new Throttler(10, 1000); ... ServiceRequest(Throtter t, ...) {
 * t.StartRequest(); .. do work ..
 * 
 * @author sergey@solyanik.com (Sergey Solyanik)
 *         http://1-800-magic.blogspot.com/2008/02/throttling-requests-java.html
 * 
 */
public class RequestThrottler {
    /**
     * The interval within we're ensuring max number of calls.
     */
    private final long _interval;

    /**
     * The maximum number of calls that can be made within the interval.
     */
    private final int _maxCalls;

    /**
     * Previous calls within the interval.
     */
    private final long[] _ticks;

    /**
     * Available element at the insertion point (back of the queue).
     */
    private int _tickNext;

    /**
     * Element at the removal point (front of the queue).
     */
    private int _tickLast;

    /**
     * the time when the last expired request occured. might be used to auto
     * disable some services all together
     */
    private long _lastExpiredMaxWait = 0;

    /**
     * Constructor.
     * 
     * @param maxCalls
     *            Max number of calls that can be made within the interval.
     * @param interval
     *            The interval.
     */
    public RequestThrottler(final int maxCalls, final long interval) {
        if (maxCalls < 1) {
            throw new IllegalArgumentException("maxCalls must be >=1, was "
                    + maxCalls);
        }
        if (interval < 1) {
            throw new IllegalArgumentException("interval must be >=1, was "
                    + interval);
        }
        _interval = interval;
        _maxCalls = maxCalls + 1;
        _ticks = new long[_maxCalls];
        _tickLast = _tickNext = 0;
    }

    /**
     * Returns the next element in the queue.
     * 
     * @param index
     *            The element for which to compute the next.
     * @return
     */
    private int next(int index) {
        index += 1;
        return index < _maxCalls ? index : 0;
    }

    /**
     * Attempts to clear the request.
     * 
     * @return Returns 0 if successful, or a time hint (ms) in which we should
     *         attempt to clear it again.
     */
    public synchronized long tryStartRequest() {
        long result = 0;
        final long now = System.currentTimeMillis();
        while (_tickLast != _tickNext) {
            if (now - _ticks[_tickLast] < _interval) {
                break;
            }
            _tickLast = next(_tickLast);
        }

        final int next = next(_tickNext);
        if (next != _tickLast) {
            _ticks[_tickNext] = now;
            _tickNext = next;
        } else {
            result = _interval - (now - _ticks[_tickLast]);
        }
        return result;
    }

    /**
     * Clears the request. Blocks until the request can execute.
     */
    public void startRequest() {
        startRequest(Integer.MAX_VALUE);
    }

    /**
     * Clears the request. Blocks until the request can execute or until waxWait
     * would be exceeded.
     * 
     * @return true if successful or false if request should not execute
     */
    public boolean startRequest(final int maxWait) {
        long sleep;
        long total = 0;
        while ((sleep = tryStartRequest()) > 0) {
            if (maxWait > 0 && (total += sleep) > maxWait) {
                _lastExpiredMaxWait = System.currentTimeMillis();
                return false;
            } else {
                try {
                    Thread.sleep(sleep);
                } catch (final InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
        return true;
    }

    public long getLastExpiredMaxWait() {
        return _lastExpiredMaxWait;
    }

}