Categories

Introduction to OSGI Declarative Services using Apache Felix

I took a look at OSGI DS and was curios about how to create a hello world bundle to run on Apache Felix. After a little search i decided that it would be a good opportunity to learn basics of maven 2. I checked out one of the projects at apache incubator svn and seeing pom.xml files I had no idea what they were used for. So for the sake of simplicity I will use Pax Construct and Pax Runner for building and running my bundle.

You should install the following software to continue this tutorial

Lets start by creating our project by typing

>mvn org.ops4j:maven-pax-plugin:create-project -DgroupId=org.example -DartifactId=ds_helloworld -Dversion=1.0-SNAPSHOT

It creates a folder named ds_helloworld and some sub directories like ds_helloworld/provisions and ds_helloworld/poms each containing a pom.xml. For what purpose these directories are used are explained here. Since we are only interested in making a hello world bundle we simply do not care.

Lets import the resulting maven projects into eclipse and see what they look like:

eclipse_pax_fresh_import

Lets move on and add a bundle to our project.

>cd ds_helloworld

>mvn org.ops4j:maven-pax-plugin:create-bundle -Dpackage=org.example.ds_helloworld -Dname=ds_helloworld -Dinternals=false -Dactivator=false
-Dinterface=false

>cd org.example.ds_helloworld

>mvn eclipse:eclipse (this will generate eclipse specific project files from pom.xml)

this will create a org.example.ds_helloworld bundle, again import it into workspace.

add org.apache.felix.scr and org.apache.felix.scr.annotations to dependencies of pom.xml of the newly created bundle

also add maven-scr-plugin to the plugins and define a goal like this:

 

        <plugin>
              <groupId>org.apache.felix</groupId>
              <artifactId>maven-scr-plugin</artifactId>
              <version>1.4.4</version>
              <executions>
                  <execution>
                      <id>generate-scr-descriptions</id>
                      <goals>
                          <goal>scr</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>

 

then go to the projects pom.xml file (/ds_helloworld/pom.xml)

and add following plugin:

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>

 

Now we need to add our source files to the org.example.ds_helloworld bundle. There are three .java files to add

org.example.ds_helloworld.HelloWorldService.java : This will define the interface that service implementation should implement. Each service is defined through an interface.

package org.example.ds_helloworld;

public interface HelloWorldService {

    public String helloWorld();
}

org.example.ds_helloworld.HelloWorldServiceImp.java : This is the component that will provide implementation for our service. Only components can provide or consume services. Every component has a default constructor(public, takes no arguments).

package org.example.ds_helloworld;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;

//This is a component so it can provide or consume services
@Component
// This component is providing the service that is defined through interface
// org.example.ds_helloworld.HelloWorldService
@Service
public class HelloWorldServiceImp implements HelloWorldService {

    public String helloWorld() {
        return "helloWorld";
    }

}

 

org.example.ds_helloworld.ServiceConsumer.java

package org.example.ds_helloworld;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.osgi.service.component.ComponentContext;

//This is a component and it consumes a service
@Component
public class ServiceConsumer {

    // Service reference is preserved in a field
    @Reference
    private HelloWorldService service;

    // When needs of the component is statisfied the component will be activated
    // by calling this function
    @Activate
    public void activate(ComponentContext cc) {
        System.out.println(this.service.helloWorld());
    }

    // When a HelloWorldService service is discovered it will be given to this
    // component through this method
    public void bindService(HelloWorldService service) {
        this.service = service;
    }

}

 

maven-scr-plugin is smart enough to generate serviceComponents.xml file and it is attached to the resulting jar file.

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
    <scr:component enabled="true" name="org.example.ds_helloworld.HelloWorldServiceImp">
        <implementation class="org.example.ds_helloworld.HelloWorldServiceImp"/>
        <service servicefactory="false">
            <provide interface="org.example.ds_helloworld.HelloWorldService"/>
        </service>
        <property name="service.pid" value="org.example.ds_helloworld.HelloWorldServiceImp"/>
    </scr:component>
    <scr:component enabled="true" name="org.example.ds_helloworld.ServiceConsumer" activate="activate">
        <implementation class="org.example.ds_helloworld.ServiceConsumer"/>
        <property name="service.pid" value="org.example.ds_helloworld.ServiceConsumer"/>
        <reference name="service" interface="org.example.ds_helloworld.HelloWorldService" cardinality="1..1" policy="static" bind="bindService" unbind="unbindService"/>
    </scr:component>
</components>

then from the command line go to the root directory of the project and type:

>mvn clean install

after some console output eventually you will see something like that:

[INFO] ————————————————————————
[INFO] Reactor Summary:
[INFO] ————————————————————————
[INFO] org.example.ds_helloworld (OSGi project) ………….. SUCCESS [5.407s]
[INFO] ds_helloworld – plugin configuration ……………… SUCCESS [0.032s]
[INFO] ds_helloworld – wrapper instructions ……………… SUCCESS [0.095s]
[INFO] ds_helloworld – bundle instructions ………………. SUCCESS [0.026s]
[INFO] ds_helloworld – imported bundles …………………. SUCCESS [0.025s]
[INFO] org.example.ds_helloworld ……………………….. SUCCESS [5.287s]
[INFO] ————————————————————————
[INFO] ————————————————————————
[INFO] BUILD SUCCESSFUL
[INFO] ————————————————————————
[INFO] Total time: 14 seconds
[INFO] Finished at: Tue Aug 10 20:43:41 EEST 2010
[INFO] Final Memory: 22M/53M
[INFO] ————————————————————————

 

goto ds_helloworld/provision/pom.xml and add dependency (this is a dependency for Apache Felix SCR but not required in the org.example.sd_helloworld bundle so we put it into provisions module. This will be used when PAX runner constructs our launcher for felix platform).

      <dependency>
          <groupId>org.apache.felix</groupId>
          <artifactId>org.apache.felix.configadmin</artifactId>
          <version>1.2.4</version>
          <type>bundle</type>
          <scope>compile</scope>
      </dependency>

Now we can create our launcher :

from command line go to the root of the project and type:

>mvn pax:provision

 

soon Apace Felix will start and output something like that:

__________                 __________
\______   \_____  ___  ___ \______   \__ __  ____   ____   ___________
|     ___/\__  \ \  \/  /  |       _/  |  \/    \ /    \_/ __ \_  __ \
|    |     / __ \_>    <   |    |   \  |  /   |  \   |  \  ___/|  | \/
|____|    (____  /__/\_ \  |____|_  /____/|___|  /___|  /\___  >__|
               \/      \/         \/           \/     \/     \/

Pax Runner (1.4.0) from OPS4J – http://www.ops4j.org
—————————————————-

-> Using config [classpath:META-INF/runner.properties]
-> Using only arguments from command line
-> Scan bundles from [C:\Users\Cihan\Documents\Blog\OSGI DS Intro\ds_helloworld\runner\deploy-pom.xml]
-> Scan bundles from [scan-pom:file:/C:/Users/Cihan/Documents/Blog/OSGI DS Intro/ds_helloworld/runner/deploy-pom.xml]
-> Provision bundle [mvn:org.apache.felix/org.apache.felix.configadmin/1.2.4, at default start level, bundle will be started, bundle will be loaded from the cache]
-> Provision bundle [mvn:org.example.ds_helloworld/org.example.ds_helloworld/1.0-SNAPSHOT, at default start level, bundle will be started, bundle will be loaded from the cache]
-> Provision bundle [mvn:org.apache.felix/org.apache.felix.scr/1.4.0, at default start level, bundle will be started, bundle will be loaded from the cache]
-> Preparing framework [Felix 2.0.2]
-> Downloading bundles…
-> mvn:org.apache.felix/org.apache.felix.configadmin/1.2.4 : 85016 bytes @ [ 14169kBps ]
-> mvn:org.example.ds_helloworld/org.example.ds_helloworld/1.0-SNAPSHOT : 5615 bytes @ [ 5615kBps ]
-> mvn:org.apache.felix/org.apache.felix.scr/1.4.0 : 185418 bytes @ [ 23177kBps ]
-> Using execution environment [J2SE-1.6]
-> Runner has successfully finished his job!

Welcome to Felix
================

-> helloWorld

 

This shows us our HelloWorldService is created bound to the component that uses it and when this component activated it printed out the text.

-> shutdown

and stop Felix.

To start this launcher and debug it we need to define a run configuration in eclipse.

Run –> Run Configurations  right click on OSGI Framework select new. A window will appear

goto Pax Runner tab and click Add POM and choose deploy-pom.xml from /ds_helloworld/runner

goto  Bundles tab and choose Felix 2.0.1 via Pax runner as Framework and uncheck all bundles

Apply and Run then you will see helloWorld on Eclipse Console Tab.

Thats all for now next time we will be writing a Component Factory to create configured services at runtime.

Karakter Karşılaştırma Sorunu – Python

Python’da yazdığım bir programın aşağıdaki parçasının False yazdırdığı farkettim:


#coding = utf-8
turkishConsonants = ['b', 'c', 'ç', 'd','f','g','ğ','h','j','k','l','m',
'n','p','r','s','ş','t','v','y','z']
word = "ağla"
print word[-3] in turkishConsonants

Bunun nedeni ğ’nin iki array elemanı olarak saklanmasıydı. word[-3] ifadesi ‘ğ’ harfinin yalnızca yarısını dönüyordu. Böyle bir durumda düzgün bir karşılaştırma yapmak için stringleri önce decode etmemiz gerekiyor.
Aşağıdaki düzeltilmiş haline görebilirsiniz.


#coding = utf-8
def contains(charArray,letter):
for c in charArray:
if(letter == c.decode('utf_8')):
return True
return False

turkishConsonants = ['b', 'c', 'ç', 'd','f','g','ğ','h','j','k','l','m',
'n','p','r','s','ş','t','v','y','z']
word = "ağla"
letter = word.decode('utf_8')[-3]
print contains(turkishConsonants,letter)

Benzer bir durum len() fonksiyonunu stringler üzerinde çağırırken de ortaya çıkıyor, yine önce stringi decode etmemiz gerekiyor.

Özel Java Olayları

Kendi Java olaylarımızı yaratmak için temel olarak 3 Java sınıfına gereksinimimiz var:

  1. Atılacak olayın sınıfı
  2. Bu olayı dinleyecek olay dinleyicilerin sorumluluğunun tanımlanacağı Java arayüzü
  3. Olayları atacak Java sınıfı

Bu sınıflar hazırlandığı zaman, diğer sınıflar kendi olay dinleyicilerini sağlayarak olayları dinleyebilirler.

Bir olay java.util.EventObject alt sınıfının olmalıdır, java.util.EventObject sınıfını genişletmelidir. AşağıdaTCP/IP üstünden mesajlar yollayan basit bir uygulama için yazdığım olay sınıfını görebilirsiniz.


package prototype.communication.events;

import java.util.EventObject;

/**
*
* @author Server
*/
public class CommunicationEvent extends EventObject {

private int eventType;
public static final int ConnectionLost = 0;
public static final int MessageReceived = 1;
public static final int ConnectionEstablished = 2;
public static final int ServerSocketFailed = 3;

public CommunicationEvent(Object source, int eventType) {
super(source);
this.eventType = eventType;
}

public int getEventType() {
return eventType;
}
}

Arayüzü yazmak genellikle çok kolaydır. Arayüzümüzün java.util.EventListener işaretleme arayüzünü alt sınıfı olma zorunluluğu unutulmamalıdır.


package prototype.communication.events;

import java.util.EventListener;

/**
*
* @author Server
*/
public interface CommunicationEventListener extends EventListener{
public void communicationEventReceived(CommunicationEvent event);
}

Üçüncü sınıfımız, diğer sınıfların olayları dinlemelerine izin vermek için aşağıdaki işlevleri sağlamalıdır:


public synchronized void addEventListener(CommunicationEventListener l);
public synchronized void removeEventListener(CommunicationEventListener l);

Aşağıdaki gibi bir değişken olay dinleyicilerini saklamak için kullanılabilir:

private List eventListeners;

Bundan sonra, yukardaki işlevlerin içeriği kendiliğinden ortaya çıkacaktır.

public synchronized void addEventListener(CommunicationEventListener l) {
eventListeners.add(l);
}

public synchronized void removeEventListener(CommunicationEventListener l) {
eventListeners.remove(l);
}

Bu sınıf ne zaman bir olay atmak isterse, olay dinleyicileri üzerinde gezerek, communicationEventReceived işlevini çağırmalıdır. Aşağıda bu işi yapan örnek bir fonksiyon görülebilir:


private synchronized void fireCommunicationEvent(int eventType) {
CommunicationEvent event = new CommunicationEvent(this, eventType);
Iterator listeners = eventListeners.iterator();
while (listeners.hasNext()) {
listeners.next().communicationEventReceived(event);
}
}

Basket Oyunu: Robot (www.onlinegames.com/basketball)

Şu aralar popüler olan bir oyuna daha Java’nın Robot sınıfını kullanarak yardımcı bir program yazdım. Bu oyunda iki boyutlu bir sahada rastgele verilen pozisyonlardan sabit noktadaki bir potaya atış yapılıyor. Bu atış yapılırken kullanıcı yalnızca topun izlediği yolun tepe noktasını belirliyor. Topun izlediği yolun bir parabole çok benzer olduğu da oyunu oynarken farkedilebilir. Haliyle atış sorunu iki noktası (pota ve topun pozisyonu) verilen bir parabolün tepe noktasını bulmaya indirgeniyor. Tabii ki, iki noktadan sayısız parabol geçebilir, bu yüzden tepe noktasının yüksekliğini her atışımız için sabit tutmamız gerekiyor. Diğer bir önemli nokta da pota ve topun parabolün ayrı kollarında olduğunun saptanması. Sonuç olarak elimizde şu veriler var

Potanın koordinatları: Px,Py

Topun koordinatları: Tx,Ty

Tepe noktasının ordinatı: H

Bulmamız gereken ise tepe noktasının apsisi: X

Parabol denklemi y = a(x-X)^2 + H

Parabolün üstende olduğunu bildiğimiz iki noktayı bu denklemde yerine koyarsak iki eşitlik elde ederiz:

1: Py=a(Px-X)^2 + H

2: Ty=a(Tx-X)^2 + H

İki denklemden a değeri çekip eşitlersek

Py–H / (Px-X)^2 = Ty-H / (Tx-X)^2

Py – H / Ty – H = (Px – X)^2 / (Tx – X)^2

(Py – H / Ty – H)^1/2 = |Px – X| / |Tx – X|

Oyundaki genel yerleşimden Px < X < Tx olduğu görülür.

(Py – H / Ty – H)^1/2 = (X – Px) / (Tx – X)

Tx * (Py – H / Ty – H)^1/2 – X * (Py – H / Ty – H)^1/2 = X – PX

Tx * (Py – H / Ty – H)^1/2 + Px = X + X * (Py – H / Ty – H)^1/2

X = (Tx * (Py – H / Ty – H)^1/2 + Px) / (1 + (Py – H / Ty – H)^1/2)

Tepe noktamızın apsisini sadece bilinen değerler cinsinden ifade ettik.

Aşağıdaki Java programı, oyunu oynamanızı yukardaki hesabı kullanarak kolaylaştırıyor. Yapmanız gerekenler: programı başlatıp oyunu açmanız, fare topun alt çizgisine getirip program fareyi atış yapılması gereken yere getirinceye kadar beklemeniz, daha sonra da tıklamanız. Yeni top belirince tekrar fareyi topun alt çizgisine getirmeniz ve döngüyü devam ettirmeniz.

Not: Aşağıdaki programda potanın koordinatları, her ekranda farlılık gösterebilir, o yüzden öncelikle bunları kendi ekranınıza göre değiştirmeniz gerekebilir, bunun için programın standart çıktıya fare pozisyonunu yazma özelliğini kullanbilirsiniz. Farenizi pota üstünde tutun, sonra da programdaki basketPositionX ve basketPositionY değerlerini çıktıya göre güncelleyin.

Not: Topun hareketi tam bir parabol olmadığı için uzak atışlarda sorun çıkabiliyor. Bu yüzden hesaplanan nokta üzerinde potaya uzaklığa göre bir düzeltme yapıyoruz. Bu düzeltmenini miktarı da ekrana bağımlı, eğer program uzak atışlarda başarız oluyorsa, optCons değişkeni küçük miktar (0.01 ya da 0.005 gibi) arttırmayı ya da azaltmayı deneyebilirsiniz.

import java.awt.AWTException;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;

/**
*
* @author Server
*/
public class Main {

/* screen dependent variables */
public static final double basketPositionX = 143;
public static final double basketPositionY = 336;
public static final double optCons = 0.03;
/* end of screen dependent variables */

public static final double shootHeightY = -44;

public static void main(String[] args) throws AWTException, InterruptedException {
Robot robot = new Robot();
Point lastLocation = MouseInfo.getPointerInfo().getLocation();
Point location = MouseInfo.getPointerInfo().getLocation();
int counter = 0;

while (true) {

Thread.sleep(100);
location = MouseInfo.getPointerInfo().getLocation();

if (lastLocation.x != location.x || lastLocation.y != location.y) {
lastLocation = location;
counter = 0;
} else {
counter++;
if (counter == 5) {
Point calculatedLocation = calculate(location);
robot.mouseMove(calculatedLocation.x, calculatedLocation.y);
System.out.println(“Coordinate Get:” + location.x + “,” + location.y);
counter = 0;
}
}
}

}

private static Point calculate(Point location) {
double x1 = location.x;
double y1 = -location.y ;
double h = shootHeightY;

double opt;

double a = Math.sqrt(basketPositionY + shootHeightY);
double b = Math.sqrt(Math.abs( -y1 + h));

double r = (x1 * a + basketPositionX * b) / (a + b);
System.out.println(r);
opt = (x1-r) * optCons;
r += opt;

return new Point((int) r, (int) -h);
}
}

DL – Safe SWRL Rules on OWL DL Ontologies with Pellet

Here is a simple example to understand the meaning of DL Safety.

In a DL Safe rule execution, only explicitly named individuals are bound to the variables in the rule.

Lets say we have a transitive object property named ancestorOf.

Can we simulate this transitivity using a DL-Safe SWRL rule rather than defining the ancestorOf property as transitive?

At the first glance it seems possible since transitivity is simply: transitive_property(?X, ?Y), transitive_property(?Y, ?Z) –> transitive_property(?X, ?Z)

To illustrate more clearly lets create the following ontology. I used Protégé 4.0 and Pellet Reasoner Plug-in 1.0 for Protégé.


test:AncestorOfOlympian
a owl:Class ;
owl:equivalentClass
[ a owl:Restriction ;
owl:onProperty test:ancestorOf ;
owl:someValuesFrom test:Olympian
] .test:Olympian
a owl:Class .test:AncestorOfChronos
a owl:Class ;
owl:equivalentClass
[ a owl:Restriction ;
owl:hasValue test:Chronos ;
owl:onProperty test:ancestorOf
] .
a owl:Ontology .test:ancestorOf
a owl:TransitiveProperty , owl:ObjectProperty .test:Uranus
a owl:Thing ;
test:ancestorOf test:Chronos .

test:Chronos
a test:AncestorOfOlympian , owl:Thing .

As expected the inferred class hierarchy is :

Now remove the transitive characteristic of ancestorOf. And Add the rule shown below.

Now classify the ontology again and look at the inferred class hierarchy.

In the first case the inference mechanism determines that AncestorOfOlympian is a super class of AncestorOfChronos.

Because Chronos is already an ancestor of some unknown individual of type Olympian and ancestorOf is transitive, then ancestor of Chronos is already an ancestor of Olympian.

Also Uranus is listed as an instance of AncestorOfOlympian.

In the second case , since there is no individual of Olympian is present, the inferences mentioned above can not be done.

Note that if we add an instance of Olympian (e.g. Zeus) and make Chronos ancestor of Zeus then Uranus is listed as an instance of AncestorOfOlympian however the inferred class hierarchy remains unchanged.

P.S. This example is a simplified version of weblog entry of Bijan Parsia.

Setting Java Character Encoding

When operations on different character sets need to be done in Java, we need to initialize JVM with required options.

First lets have a look at basics of java character encodings.

  • Internally the JVM always operates with Unicode.
  • Data transferred in or out of the JVM is converted to a format specified in the file.encoding property of the JVM
    • Data transferred in the JVM is converted from the format specified at file.encoding to Unicode
    • Data transferred out of the JVM is converted from Unicode to the format specified at file.encoding
  • When data need to be processed from Java Program other than the format specified in file.encoding the following classes which allows usage of encodings that takes precedence over the default one can be used
    • java.io.InputStreamReader
    • java.io.FileReader
    • java.io.OutputStreamReader
    • java.io.FileWriter

Default character set of the JVM varies across platform. Following piece of code shows how to get default character set of JVM.


System.out.println(System.getProperty("file.encoding"));
System.out.println(
new java.io.OutputStreamWriter(
new java.io.ByteArrayOutputStream()).getEncoding()
);
System.out.println(java.nio.charset.Charset.defaultCharset().name());

Output on linux

ANSI_X3.4-1968
ASCII
US-ASCII

This property can be set using System.setProperty(“file.encoding”, {desired encoding});

However doing this did not help me much since, the core Java libraries does not use this mechanism to determine default encoding.

My problem was to read from an java.net.URLConnection so i used the following piece of code:


URL url = new URL(urlStr);
URLConnection connection = url.openConnection();

//Create InputStreamReader with UTF8 Charset
BufferedReader in = new BufferedReader(new InputStreamReader(connection
.getInputStream(), Charset.forName("UTF-8")));

// If we need to read this stream into a string we need to create the string like:
String str = new String(bytes, Charset.forName("UTF-8"));

BlazeDS - Remote Object Service Tutorial

BlazeDS’in Remoting Object Service i, Flex uygulamalarindan Java Server lara uzak yordam cağrısı (remote procedure call) yapmak için kullanılır.

Bir uygulama sunucusuna (Tomcat i kullandım) BlazeDS deploy edildikten sonra , aşağıdaki adımlarda, bir Java Server dan bir Flex uygulamasına nasıl Person and Car adlı nesnelerin uzak yordam cağrısıyla gönderileceğini inceleyeceğiz.

Sunucu Tarafındaki Kodlama ve Yapılandırma

Bu uygulamayı Net Beans te bir Java Web Application kullanarak olusturabiliriz.

Metodları cağrılacak olan Java class ları aşağıdaki özelliklere sahip olmalıdır.

  • Java class ı “public” olarak tanımlanmalıdır.
  • Uzak yordam cağrısıyla erişilmek istenen methodlar “public” olarak tanımlanmalıdır.

Aşağıda Flex uygulamasına Person class ının örneklerini gonderecek olan deneme.Manager ın kodu gorunuyor:


package deneme;

import java.util.ArrayList;
import java.util.List;

/**
*
* @author Cihan
*/
public class Manager {

public List persons = new ArrayList();

public Manager() {
//We have no persistence
//So create some dummy data to send
Person person1 = new Person();
Person person2 = new Person();
Car car1 = new Car();
Car car2 = new Car();

person1.setName("Person1");
person2.setName("Person2");

car1.setModel("Model1");
car2.setModel("Model2");

person1.addCar(car1);
person2.addCar(car2);

persons.add(person1);
persons.add(person2);

}

//The method that will be invoked
public List getPersons() {
return persons;
}
}

Sunucu tarafındaki yapılandırmayı tamamlamak için iki işlem daha yapmamız gerekiyor :

  • {Project_Root}/build/web/WEB-INF/classes dizinindeki klasörleri{BlazeDS_Root}/WEB-INF/classes dizinine kopyalamalıyız
  • {BlazeDS_Root}/WEB-INF/flex/remoting-config.xml dosyasındakı “service” elemanın altına asağıdaki “destination” elemanını ekleyin


deneme.Manager
application




İstemci Tarafındaki Kodlama

İstemci tarafı için sunucu olarak J2EE ve uzak nesne erişim servisi olarak LiveCycle Data Services kullanan bir Flex Projesi oluşturup sunucu ayarlarını aşağıdaki gibi yapılandırdım:

Artık uzak yordam çağrısı yapabilmemiz için ActionScript te bir mx.rpc.remoting.RemoteObject oluşturup getPersons() metodunu cağırmak kalıyor.

Bu çağırma zaman uyumsuzdur ve sunucunun yanıtı aşağıda belirtilen iki türden biridir. (Bu yanıtların nasıl alınıcağı aşağıdaki kodda görülebilir) :

  • result fieldında cağrılan metod un döndüğü değeri tasıyan mx.rpc.events.ResultEvent nesnesi
  • İşlem sırasında herhangi bir hata olusursa, bir mx.rpc.events.FaultEvent nesnesi

Flex uygulamasının .mxml ve .as dosyaları:




import deneme.Car;
import mx.events.ListEvent;
import mx.events.DataGridEvent;
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.remoting.RemoteObject;
import mx.collections.ArrayCollection;
import deneme.Person;

private var manager:RemoteObject;

[Bindable]
private var persons:ArrayCollection;

[Bindable]
private var selectedPerson:Person;

[Bindable]
private var selectedCars:ArrayCollection;

private function init():void{
//Argument given to the constructor should be same as the 'id' of the destination
manager = new RemoteObject("PersonManager");

//Add EventListener for result case
manager.addEventListener(ResultEvent.RESULT, onGetPersonsResult);
//Add EventListener for fault case
manager.addEventListener(FaultEvent.FAULT, onGetPersonsFault);
//Call function using the same name as the method of Java class
manager.getPersons();
}

private function onGetPersonsResult(event:ResultEvent):void{
//Remove EventListeners
manager.removeEventListener(ResultEvent.RESULT, onGetPersonsResult);
manager.removeEventListener(FaultEvent.FAULT, onGetPersonsFault);

//Store result in a variable
persons = event.result as ArrayCollection;

}

private function onGetPersonsFault(event:FaultEvent):void{
//Remove EventListeners
manager.removeEventListener(ResultEvent.RESULT, onGetPersonsResult);
manager.removeEventListener(FaultEvent.FAULT, onGetPersonsFault);

//Display fault message in a popup window
Alert.show(event.fault.message);
}

private function onChange(event:Event):void{
selectedPerson = person_dg.selectedItem as Person;
selectedCars = (person_dg.selectedItem as Person).cars;

}

]]>












package deneme
{
//Remote Class alias should be the fully qualified name of the Remote Class
[RemoteClass(alias="deneme.Car") ]

public class Car
{

//fields should be declared as "public" with same name and type
public var model:String;

//Default constructor should be declared
public function Car()
{
}

}
}


package deneme
{
import mx.collections.ArrayCollection;

[RemoteClass(alias="deneme.Person") ]
public class Person
{

public var name:String;
[Bindable]
public var cars:ArrayCollection;

public function Person()
{
}

}
}

Person ve Car için .java dosyaları

package deneme;

public class Car {
public String model;

public Car() {
}

public void setModel(String model) {
this.model = model;
}

public String getModel() {
return model;
}

}



package deneme;

import java.util.ArrayList;
import java.util.List;

public class Person {

public String name;
public List cars;

public Person() {
cars= new ArrayList();
}

public void setCars(List cars) {
this.cars = cars;
}

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

public List getCars() {
return cars;
}

public String getName() {
return name;
}

public void addCar(Car car) {
cars.add(car);
}
}

Farmville: Tıklama Robotu

Farmville gibi oyunlar oynarken çok sayıda tıklama yapmak gerekiyor. Bu otomatik olarak yapmak için öncelikle xdotools adlı sahte klavye ve fare girdisi üretmeye yarayan bir araç kullandım, fakat xdotools sadece X11 sistemini desteklediği için platform bağımsızlığını sağlamak adına Java kullanarak aynı işlemi yapmaya karar verdim.

Java’da sahte girdi üretmek amacıyla java.awt.Robot sınıfı kullanılıyor. Bu sınıfı kullanarak sahte tıklama, fare orta tuş çevrilmesi, klayve girdisi, imleç yeri değiştirme gibi işlemleri kolayca yapabilirsiniz.

Aşağıda önce farenin konumunu değiştirip sonra tıklama üreten basit bir Robot kullanımı görebilirsiniz:

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;

public class Main {

public static void main(String[] args) throws AWTException {
Robot robot = new Robot();

robot.mouseMove(100, 100); //move mouse
robot.mousePress(InputEvent.BUTTON1_MASK); //press left button of mouse
robot.mouseRelease(InputEvent.BUTTON1_MASK); //release left button
}
}

Aşağıda bir arkadaşımın tarlası için yazılan programı görebilirsiniz


package farmville;

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;

/**
*
* @author Server
*/
public class Main {

/**
* @param args the command line arguments (not used)
* @throws AWTException
* @throws InterruptedException
*/
public static void main(String[] args) throws AWTException, InterruptedException {
Robot rbt = new Robot();

int startX = 718;
int startY = 706;
int startPosX = 718;
int startPosY = 706;
Thread.sleep(3500); //sleep while I switch to facebook and make the window fulscreen
rbt.mouseMove(startPosX, startPosY); // start at x=718 and y=706
int x = 25;
int y = 12;
for (int j = 1; j < 23; j++) {
for (int i = 1; i < 22; i++) {
rbt.mousePress(InputEvent.BUTTON1_MASK);
rbt.mouseRelease(InputEvent.BUTTON1_MASK);
rbt.mouseMove(startPosX += x, startPosY -= y);
}
rbt.mousePress(InputEvent.BUTTON1_MASK);
rbt.mouseRelease(InputEvent.BUTTON1_MASK);
startX -= x;
startY -= y;
startPosX = startX;
startPosY = startY;
rbt.mouseMove(startPosX, startPosY);
}
}
}

Çok Sayıda Ayraçla Uğraşmak Gerekince…

Bir önceki yazımda sözünü ettiğim lambda calculus işlemleriyle uğraşırken, zaman zaman çok fazla ayraç (parantez) ortaya çıkıyor. Örneğin:

λx.λy.+ x y ifadesine denk olan SKI ifadesini bulmaya çalışırken

S (S (K S) (S (K (S (K +))) (S (λx K) (λx x)))) (λx I) gibi bol ayraç içeren ara basamaklara rastlanabiliyor. Bu gibi ifadelerle uğraşırken, KDE’nin (www.kde.org) Kate adlı metin düzenleyicisi işleri kolaylaştırabiliyor. Kate’in Scheme programla dili için renklerdirme desteği, içe içe ayraçları yedi farklı renkle renklendirerek çok ayraçlı ifadeleri daha kolay anlaşılır hale getiriyor. Bu özelliği, Kate’in menüsünden Araçlar->Renklendirme->Betikler->Scheme’i seçerek kullanabilirsiniz. Çalıştığınız dosyanın uzantısını “scm”, “scheme”, “guile” ya da “ss” yaparak da aynı etkiyi elde edebilirsiniz.

Aşağıda λx.λy.+ x y ifadesinin SKI karşılığının bulunuşunu renklendirilmiş halde görebilirsiniz.

λ-Calculus İfadelerini SKI İfadesine Dönüştürme

S, K ve I’ı şöyle tanımlayın

S x y z = x z (y z)

K x y = x

I x = x

Bir lambda calculus ifadesini yukarıda tanımladığımız kombinatörlerle ifade etmek için aşağıdaki üç kuraldan birini, hiçbiri uygulanamaz hale gelinceye kadar uygulayın

1) λx.e1 e2 => S (λx e1) (λx e2)

2) λx.x => I

3) λx.c => K c [Burada c terimi x serbest değişkenini içermemelidir.]

Örneğin:

λx.+ x x ifadesine karşılık gelen SKI ifadesini bulalım.

lambda-calculus ifadeleri soldan birleşme özelliği gösterdiği için:

λx.+ x x = (λx(+x) x)

Bu ifadeye 1. kuralı uygularsak:

(S (λx + x) (λx x))

Yeniden 1. kuralı uygularsak

(S (S (λx +) (λx x)) (λx x))

Sırasıyla 3.,2. ve yeniden 2. kuralı uygularsak yalnızca SKI terimlerini içeren aşağıdaki ifadeye ulaşırız

(S (S (K +) I) I)

Görüldüğü gibi lambda-calculus ifademizden, değişken bağımsız SKI ifadesi elde ettik. Bu ifadeye bir argüman uygularak doğruluğunu kontrol edebiliriz.

Örneğin:

(S (S (K +) I) I) 3 [Burada S kombinatörü (S (K +) I), I ve 3 argümanlarıyla çağırılmıştır. S kombinatörünün tanımından bu ifadeyi hesaplayabiliriz]

(S (K +) I 3) (I 3)

(K + 3) (I 3) (I 3)

+ 3 3

6