2013. augusztus 9., péntek

scala - slick - left join

I'm going to switch to English for the sake of this post.

While playing with Play Framework, Slick and Scala recently, I came across this problem when doing a left join:
[error] SlickException: Read NULL value for column ORDERS.GUEST_ID (TypeMapper.scala:158) [error] models.BarTables$$anonfun$currentTableStateFull$1.apply(BarTable.scala:108)
Let's see what happens here:

        for{
            (guests,orders) <- Guests leftJoin Orders on (_.id === _.guestId)
        } yield (guests,orders).list

So this is how you do a left join with Slick. Here's the two tables used in the query:

object Orders extends Table[Order]("ORDERS") with CRUDModel[Order] with Logger{

  def id = column[Long]("ID", O.PrimaryKey, O AutoInc) // This is the primary key column
  def guestId = column[Long]("GUEST_ID")
  def created = column[DateTime]("CREATED")
  def delivered = column[Option[DateTime]]("DELIVERED")
  def paid = column[Option[DateTime]]("PAID")

  def * = id.? ~ guestId ~ created ~ delivered ~ paid <> (Order.apply _, Order.unapply _)

...
 
object Guests extends Table[User]("GUESTS") with CRUDModel[User]{

  def id = column[Long]("ID", O.PrimaryKey, O AutoInc) // This is the primary key column
  def name = column[String]("NAME")
  def email = column[String]("EMAIL")

  def * = id.? ~ name ~ email <> (User.apply _, User.unapply _)

...

That looks quite normal I guess.

But then the problem arises when there's no orders belonging to the guests, and so all the columns selected from the Orders table are null. And guestId cannot be null, it's not defined as an Option (obviously).

What am I doing wrong?

The problem is that the default projection * is used when yielding the result:
    
    yield (guests,orders).list

We have to provide a projection that doesn't use the default one. So after some googling and stackoverflowing, I came across this post, and then this one and the result looks like this:

  def maybe = id.? ~ guestId.?  ~ created.?  ~ delivered  ~ paid  <> (
      tupleToOrder _,
      (order: Option[Order]) => None
  )
  
  def tupleToOrder(orderTuple: (Option[Long],Option[Long],Option[DateTime],Option[DateTime],Option[DateTime])) : Option[Order]= orderTuple match {
  case (Some(id),Some(guestId),Some(created),delivered,paid) => Some(Order(Some(id),guestId,created,delivered,paid))
  case (None,_,_,_,_) => None
  }

So instead of using the values as they would be not-nulls, we provide a way to pass nulls, and then get an Option[Order] instead of an Order. We only have to match for Some(id) really, since if that's a null, all the other columns are null as well.

And so the original query looks like this:
    for{
        (guests,orders) <- guests(tableId) leftJoin Orders on (_.id === _.guestId)
    } yield (guests,orders.maybe)

So finally this mystery is resolved now!

2013. június 28., péntek

CDI event + JMS - szinkron és aszinkron események


Kétféle eseményt különböztetünk meg aszerint, milyen időben (pontosabb Threadben) futhat le:
  • szinkron (a hívó threadben fut),
  • aszinkron (nem a hívó threadben fut).
A CDI eseménykezelése segítségével valósítjuk meg mindkét fajtát.

Szinkron esemény

CDI event fire -> CDI event handle with @Observe
class Producer{
   
    @Inject @InForeground
    Event<MyEvent> myEventToBeFiredInSync;

...
    void myMethod(){
        ...
        //do the business
        myEventToBeFiredInSync.fire(new MyEvent());
        ...
    }
}

class Consumer{

...
    void consumeAndHandleEvent(@Observe @InForeground MyEvent myEvent){
        ...
        //do the business
        workWith(myEvent);
        ...
    }
}
Például:
TransactionEvent -> automatikus history és üzenetkezelés az ügylethez

Aszinkron esemény

Ez JMS messaging segítségével van megvalósítva. A keletkezés helyén azonban lecsatoljuk a JMS üzenetet generáló logikát az üzleti részről, és CDI esemény segítségével pukkan el az aszinkron üzenet is.
CDI event fire -> JMS Producer @Observe and send message -> JMS consumes message and CDI event fire -> CDI event handle with @Observe
class Producer{

    @Inject @InBackground
    Event<MyEvent> myEventToBeFiredAsync;

...
    void myMethod(){
        ...
        //do the business
        myEventToBeFiredInSync.fire(new MyEvent());
        ...
    }
}

class Consumer{

...
    void consumeAndHandleEvent(@Observe @InForeground MyEvent myEvent){
        ...
        //do the business
        workWith(myEvent);
        ...
    }
}
A Consumer nem tudja megenni az eseményt, hiszen az @InForeground eventet vár. Itt jön a JMS:
class JMSMessageProducer{

...
    @Inject
    private QueueSession session;

    @Inject
    private Queue queue;

    public void produceJMSMessage(@Observes @InBackground MyEvent myEvent) {

        try {
            QueueSender sender = session.createSender(queue);
            Message message = session.createMessage();
            message.setObjectProperty("myEvent", myEvent);
            sender.send(message);
        } catch (JMSException e) {
            logger.error("Error sending message to queue", e);
        }
    }
}

@FancyAnnotations
class ConsumerMDB{

...
    @Inject @InForeground
    Event<MyEvent> myEventToBeFiredInSync;
    

    @Override
    public void onMessage(Message rcvMessage) {
        try {
            MyEvent myEvent = (MyEvent)rcvMessage.getObjectProperty("myEvent");
            myEventToBeFiredInSync.fire(myEvent);
        } catch (JMSException e) {
            logger.error("Incorrect message format.", e);
        }
    }
}
Tehát gyakorlatilag visszatranszformálja a JMS üzenetet CDI eseménnyé.
Az előny, hogy az üzleti kódban kizárólag CDI eseményeket találunk, és a szinkron-aszinkron események között egy annotáció lecserélésével tudunk váltani, akár programmatikus módon.
Például:
A kérelem benyújtása után aszinkron módon készítjük fel az ügyletet az alapítvány oldali befogadásra.

JMS erőforrások megadása CDI segítségével

package hu.avhga.business.common.resource;

import javax.annotation.Resource;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.Session;

/**
 * JMS erőforrások előállítására és lezárására használt osztály
 *
 * @author bnemeth
 *
 */
public class JMSResources {

    @Resource(mappedName = "java:/JmsXA")
    private QueueConnectionFactory connectionFactory;

    @Produces @AdmissionQueue @Resource(mappedName = "java:jboss/exported/jms/queue/transactionAdmissionMDBQueue")
    private Queue admissionQueue;

    @Produces @AssessmentQueue
    @Resource(mappedName = "java:jboss/exported/jms/queue/transactionAssessmentMDBQueue")
    private Queue assessmentQueue;

    @Produces @AssessmentQueue
    public QueueSession createAssessmentSession(@AssessmentQueue QueueConnection conn) throws JMSException {
        return conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    }

    @Produces @AssessmentQueue
    public QueueConnection createAssessmentConnection() throws JMSException {
        return connectionFactory.createQueueConnection();
    }

    public void closeAssessmentSession(@Disposes @AssessmentQueue QueueConnection conn) throws JMSException {
        conn.close();
    }

    public void closeAssessmentSession(@Disposes @AssessmentQueue QueueSession session) throws JMSException {
        session.close();
    }

    @Produces @AdmissionQueue
    public QueueConnection createOrderConnection() throws JMSException {
        return connectionFactory.createQueueConnection();
    }

    @Produces @AdmissionQueue
    public QueueSession createOrderSession(@AdmissionQueue QueueConnection conn) throws JMSException {
        return conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    }

    public void closeOrderSession(@Disposes @AdmissionQueue QueueConnection conn) throws JMSException {
        conn.close();
    }

    public void closeOrderSession(@Disposes @AdmissionQueue QueueSession session) throws JMSException {
        session.close();
    }
}

A fenti osztály lehetővé teszi megadott Queue és QueueSession injektálását, továbbá nem kell explicit módon lezárni sem az erőforrásokat, erre való a @Disposes annotáció.

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

2013. április 25., csütörtök

JBoss 7 remote EJB lookup

Felírom, mert már legalább másodszor szívom meg.

Ha ezt írja ki a JBoss 7 a modul deployolása után:

java:global/cdi_events_poc_ear/cdi_events_poc/TransactionServiceBean!hu.avhga.service.TransactionServiceR
java:app/cdi_events_poc/TransactionServiceBean!hu.avhga.service.TransactionServiceR
java:module/TransactionServiceBean!hu.avhga.service.TransactionServiceR
java:jboss/exported/cdi_events_poc_ear/cdi_events_poc/TransactionServiceBean!hu.avhga.service.TransactionServiceR
java:global/cdi_events_poc_ear/cdi_events_poc/TransactionServiceBean!hu.avhga.service.TransactionService
java:app/cdi_events_poc/TransactionServiceBean!hu.avhga.service.TransactionService
java:module/TransactionServiceBean!hu.avhga.service.TransactionService

Akkor próbálhatunk lookupolni pl. a legfelsőre, az eredmény:

java.lang.IllegalStateException: No EJB receiver available for handling [appName:java:global,modulename:cdi_events_poc_ear,distinctname:cdi_events_poc] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@374d2f77
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:584)
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:119)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:136)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104)
at $Proxy4.submit(Unknown Source)
at hu.avhga.TestHistory.aaaa(TestHistory.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:46)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:43)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:270)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:62)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:52)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:307)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Az Exception egyébként el is árulja, de amúgy utólag okos az ember:
[appName:java:global,modulename:cdi_events_poc_ear,distinctname:cdi_events_poc]

Hát persze, hogy nem java:global az appName! Tehát ha azt a prefixet levesszük, rendesen megtalálja a keresett szolgáltatást a lookup. Nem az mondom, hogy ha java:globallal kezdődik a String, akkor dobjon külön exceptiont, hogy "nézz már oda mivel kezdted, Géza!", de elég nehezen észrevehető hiba.

Emellett még ugye kell a jboss-ejb-client.properties, a client jar, és kábé ennyi, amit fél évente elfelejtek, és nem 10 perc összekalapálni a remote tesztet.

2012. szeptember 25., kedd

Kötelező irodalom

Belebotlottam egy blogolt listába, majd a kommentek közt annak felmondásába, és gondoltam, megosztom itt is - csak nem hülyeségeket beszélnek! Némileg megnyugvással tölt el, hogy párat már olvastam, vagy legalábbis hallottam róla.

Az ember persze képes néha elszállni, de egy-két szakmai vita nála tapasztaltabbakkal rögtön visszaszögeli a székébe, ilyenkor persze nehéz vitatkozni a következővel is:

"As described in many books, a Journeyman is a developer who knows his language and has done smaller projects but still has a long way to go to being a professional. At the beginning of this stage I’m sure you didn’t agree with this statement (I didn’t, either)."

Na ilyenkor segítenek legalábbis ezek a könyvek: első ajánlás meg ezek második ajánlás. Csak az elsőket írom ki külön.

Kezdők:
  1. Head First Java
  2. A Beginner’s Guide
  3. Test Driven Development by Kent Beck
  4. SCJP Sun Certified Programmer for Java 6 (+1)
Az első szinten nekem mindjárt ki is marad kettő, hiszen a nyelvvel nem ezekből ismerkedtem, hanem rögtön az SCJP vizsgakönyvvel meg a mélyvízzel, viszont a harmadik érdekes. Kent Beck Test Driven Developmentje úgy néz ki, megkerülhetetlen, és jómagam is érzem, vajmi kevés a tudásom a témában. Sajnos azt kell mondanom, idehaza az ilyen szemléletű fejlesztésre eddig kevés igény mutatkozott, de persze ez önmagában sem arról szól, hogy másokat kényszerítsünk, sokkal inkább magunkat. Annyival talán vitatkoznék, hogy ez mennyiben beginner szint, de vitán felül áll, hogy kötelező.

Haladó:
  1. Effective Java by Joshua Bloch
  2. The Pragmatic Programmer
  3. Design Patterns Book by the Gang of Four
  4. Refactoring Book by Martin Fowler
  5. Clean Code by Robert C. Martin
  6. The OSGi in Action
  7. The Clean Coder by Robert C. Martin
Na ez már érdekesebb. Az Effective Javát nemrég olvastam, talán eddig a legnagyobb hatást ez a szakkönyv tette rám szemléletben, de emögött szorosan ott van az 5-ös jelzésű Clean Code is. Ugyan az utóbbinak elég sok kritikájával találkoztam azóta, talán az elv, a szemlélet a fontos, ahogy nyilván Josh Bloch minden szavát sem tekinthetjük szentírásnak. A Gang of Four tervezési mintákról szóló könyve minden második szakmai fórumon előjön, interjúk előtt is kötelező belepillantani - persze ez ismét egy olyan anyag, amelynek nagy részét akkor is ismerjük, ha magáról a könyvről még nem hallottunk. Vagy egy általuk népszerűsített egy minta, vagy már "eleve" az volt.

Profiknak:
  1. Java Concurrency in Practice by Brian Goetz
  2. Woking Effectively with Legacy Code by Micheal Feathers
  3. Peopleware by Tom DeMarco, Timothy
  4. Patterns of Enterprise Application Architecture by Martin Fowler
Az első témában még most is bőven zavarba hozható vagyok, a második egy dögunalmas projektben való kihívástalálásban segít (azt hiszem, SzántóPé ajánlotta), a harmadik projektmenedzsment témakörben írt (Szentner Tomi ajánlotta), aztán az utolsó megint csak egy olyan topik, ami mostanában elég gyakran foglalkoztat.

Szóval számomra a K3, P3, P4, H7, H4 érdekességi sorrendben a bepótlandó, a többi csak ez után.

Ti mivel egészítenétek ki?

2012. július 24., kedd

Víge

Na szóval kábé mindenki tudja már, hogy állok, viszont nem volt erről kedvem írni egy sort sem - de talán nem is volt miről.

Jött pár megoldási javaslat:
- átmenni a szomszédcsapatba, mert ők jóval technikaibb feladatokat látnak el - válasz: a nullánál az egy erősebb, de még mindig távoli a tíztől, ugyanazt a komponenst hegesztik, miért lenne technikaibb?
- átmenni frontendesekhez - önmagában megmosolyogtató, hát miről beszéltem nektek eddig?
- átmenni a vasúthoz - úgy dögöljek meg, ha értem, de ugyanazt a rendszert használják, csak vonatokra van cserélve minden, hát ez mégis mitől jelentene több kihívást?
- még két ilyen, amit már el is felejtettem.
Oda ahova esetleg érdemes lenne bekerülni, csak több év céges tapasztalat után lehet csapatváltással. De persze a végén már teljesen mindegy volt, mit mondanak, csak húzhassak el innen.

De persze a pétanque jó volt. A legdurvább érv, amit valaha hallottam.

Pétanque Antibes-ban

Remek munkahely: végy huszonegynehány embert, oszd őket hármas csoportokra, adj mindegyiknek hat golyót, állíts párba két csoportot, dobd el a dugót és hagyd őket játszani két órán át. Ismételd meg fél évente vagy gyakrabban az elégedettség növeléséért.

Bravó.

Erről jut eszembe, hogy még a végén tanultam pár hasznos kifejezést. Olaszul.

Kifele távozó ember lever valamit a polcról.
JÓZSEF (halkan, bizonytalanul): Vaffanculo.
40-es JÓL KARBANTARTOTT ELADÓ NŐ (JÓZSEF-hez, elismerően): Bravo! Che culo!

Ezen kívül che cazzo, illetve kifejezett tárggyal testa di cazzo. Még jól jöhet.

A lakótársak megértőek voltak. Én biztos nem lettem volna ilyen megértő. De ők is mintha készültek volna rá. Illetve a srác, mert a csajjal elég minimálisra sikerült a kommunikáció. Annyira azért nem volt hideg a viszonyunk, hogy ne tudott volna rám írni a távozásom után egy héttel, hogy valószínűleg az én vendégeim (lányok, bizonyára) eltulajdonítottak pár pipereterméket.

In the bathroom was Vita Liberata bronzer, in my bedroom on the shelf was a Chanel nail polish very dark red, and Paco Rabanne Lady Million perfume.


Sure, lah! Mindenesetre csak 50 eurót vontak le emiatt a kaucióból. A végén jobban is jártam, mint számítottam rá. A teljes kaucióból ennyi ugrott, de visszakaptam 1 hétre való lakbért, mert hogy előbb leléptem. Merci beaucoup. Ezt még a srác is érti, meg még: enchanté. Két év alatt azért egész korrekt teljesítmény. Bár amúgy jó srác.

Na szóval 29-én reggel a global news után, illetve annak részeként mondtam, hogy akkor köszöntem a lehetőséget. Páran kicsit néztek, nem értették, hogy álmaik munkahelyét hogy hagyhatja itt valaki. Az olasz lány azért jófej volt, elmondta, hogy 2 hét múlva ő is lép, igaz, egy másik csapathoz androidot hegeszteni, meg hogy "le se szarja, hogy mi történik ezzel a fos flexpricerrel, rémálom az egész". Bravo. Gratulált továbbá az elköszönő szövegemhez is, amit egyébként nem értett elsőre teljes mértékben, és a humor eszköze elfedte előle a megbúvó tartalmat.

Szóval van ez a csokis sütemény, töltelékkel, amiért többen annyira odavagytok a pénteki napon. Kipróbáltam, és hát nem rossz, de biztos ismeritek azt a fehér sajtkrémet, fügés, de főleg a gesztenyés krémmel a tetején. Nos, nekem az a kedvencem. És ez az oka annak, hogy most elmegyek.

Fromage blanc aux marrons

Loïc rákérdezett, hogy mi a valódi oka annak, hogy elmegyek, mert szerinte nem a sütemény. Hát - a kurva életbe! - annyira bonyolult volt megemészteni (habár a desszerteknél járunk) ezt a metaforát, meg hogy az én számomra mást jelent a minőségi munkahely? - gondoltam, de elmagyaráztam neki pontosan, mi volt a bajom. Illetve egész pontosan nem, mivel nem akartam az ő kedvét is teljesen elvenni az Amadeustól. Mondjuk nem sok sansz lett volna erre.

Az egyetlen ember, akit tényleg zavart kicsit, hogy elhúzok, az a marokkói Zakaria volt. Sajnos nem az én csapatomban volt, de viszonylag motivált srác, kár, hogy ennél a cégnél tölti a legszebb, legtermelékenyebb éveit, vagy azokból akár egyet is. A végén még megpróbált meggyőzni, hogy együtt (kiegészülve az ír Darrennel) építünk valami mellékprojekt keretein belül egy eclipse plugint, ami arra jó, hogy nem figyeltem oda, mire. Találkoztam vele szombaton is, a strandon. Nagy szarházi. Volt nála egy kártyapakli, olyan trükköket mutatott, hogy ha beszartam, akkor sem jöttem rá, hogy csinálta. Ismerte Somát is, aki - ugye - a magyar bűvészvilágbajnok. Mondtam neki, ha Pesten jár, bemutatom neki. Habár én is csak egyszer találkoztam vele Bálintéknál (most már az csak Julcsinál), de ezt neki nem kell tudnia. De én is vittem azért ebbe a haverkodásba: folyamatosan adagolva, már a második héttől elkápráztattam azzal, hogy válogatottabbnál válogatottabb káromkodásokat tudok az ő nyelvén, állítólag olyanokat is, amelyeket még életében nem mert a szájára venni. Meg persze a marihuánafogyasztás bármilyen szakkifejezése csípőből: tkief?

Szóval a szociális netvörkök közül egy olasz és egy marokkói plusz a fácsén, egy ír a linkedinen. Ennyi a termés onnan.

Jocó meg hétfőn jött meg értem. Hullafáradt volt már este 11 felé, Sopronból egyedül nyomta le egy kis jesolói kitérővel meg milánói eltévedéssel (a GPS a gyengék fegyvere). Szerencsére a város másik végén állt meg, 20 perc erőltetett menetben, hogy elérjem. Azé örültem neki.

Másnak fürödtünk Cannes-nál, megálltunk St. Tropez-ban, ettünk pizzát (ócsó), megittunk egy Impression Rouge-t (Pfneiszl csúcsbor), aludtunk a tengerparton a kocsiban (VW Caddy, ülés kivéve), reggel kibasztak minket, hogy fizetős a parkoló (möszjő, vú reszté iszí? zsö nö parl pa franszé, persze, hogy értettük, fizess vagy húzz el), továbbhajtottunk, boltban vettünk tejet, baguettet, paradicsomot, megálltunk a szikla tetején,

Józsi áll az úton Cannes után, de amúgy a kép készülhetett volna tartalma alapján akár a Mecsekben is, de nem ott készült

megettük, továbbhajtottunk, egy városban, ahol olyan út vezet be fél kilóméter hosszan, hogy jobbról balról virágzó leanderfal határolja (giccs), ittunk egy jó kávét (én), egy jó drága capuccinót (Jocó, aki nem tudta, hogy csak a kávé ócsó), nézegettük a  (főleg utólag) meseszép pincérnőt, aztán fürödtünk egy olyan öbölben, aminek (ha félkör alakú volna) a sugara kábé 20 méter, a szikla esése 30 méter 5 méteren, buzeráltunk egy döglött medúzát, nézegettük a feltehetőleg francia srác feltehetőleg francia (és hát főleg utólag) álomszép barátnőjét, de az is lehet, hogy ez még előző nap volt, mert különben nem jönne ki sehogy sem, hogy átmenjünk Toulonon, ami a Riviéra gyöngyszeme (még észak-angol szemmel is ronda iparváros), aztán elérjük Marseille-t,

egy csodaszép épület Marseille-ből

együnk egy jó ebédet kettőkor a világ leglecsúszottabb bárjában, fonnyadt salátával, csirke saslikkal, viszont élvezhető pudinggal és élvezhetetlen sörrel, felmenjünk aztán az erődbe, eléggé megizzadjak, én csak felfelé nem szeretek menni, Papa, tudod, hogy hazamennék gyalog, ha nem lenne az Alpok, aztán belváros, bevásárló kocsik megfigyelése a Régi Kikötő vizében, utcák felújítása, minden elismerésem, én ennyit nem tudnék letérkövezni, a térkövezés a legszarabb munka, Papa, szarabb, mint a mulcsozás?, persze, a mulcsozás az egy hálás munka, Papa, aztán kicsit kijjebb menve, jó 15 percet töltöttünk a viszonylagosan rasszista ki tud előbb összeszámolni tíz nem bevándorlót játékkal, aztán megtaláltuk végre az óvárost, ahol egy apró téren megittunk egy kiváló Ricard-t (vagy csak én, mert Jocó vezetett, ő a századik kávét, persze én is), ahol a Plus belle la vie, avagy francia barátokközt játszódik a 13 cantons téren, ami nem is csoda ezek szerint, mert itt van a gazdagok és szegények ütközőpontja, ami a sorozat egyik konfliktuseredője egyben, és amelynek ott a téren azért egy külön kis szuvenírboltja is van, meseszép eladólánnyal, de idő továbbra sincs, ennyi volt Marseille, kábé, pár utcafotó,

mine!

templom, közlekedési táblák gondosan belekomponálva (Jóska témája),

stílus születőben - @joskapista
pár munkagép (az én témám),
a berlini sorozat méltó párja - @balazsmaria

egy könyvtár, rohanás, megállás a parton később, fürdés a tengerben, legalább van zuhany a parton, van baguette, van taboulé, van Shiraz (Pfneiszl csúcsbor), van frizbi, vannak helyi középiskolások, akik éjjel 1-ig pétanque-oznak, vannak iskoláslányok, akik őket nézik, s ahogy a pálya pora egyre inkább rátelepszik az adidas melegítő szárára. Van alvás nekünk a Caddy-ben, van a német házaspárnak a skodában, van a vanabíhippiknek a transzporterben. Reggel be a tengerbe, zuhany, még mindig nem szappannal, de az kinek is kell, George Carlin szerint is elég hetente egy rendes tisztálkodás, apám szerint is talán, szerintem meg főleg, habár nem a tisztálkodás miatt zuhanyzunk, passzió csupán, az indonézek például napi háromszor is megfürdenek, megmandiznak, kakk, kimos, látod, egyszerűbb, a papír csak eltömítené, jobbkézbe a vödröcske, belemerít, ballal nedvedít, töröl, aztán azt másra nem használ, enni, ne, érinteni, szentségtörés, de visszaülök, napszemüvegemet felteszem, bámulok a hajnali tengerre (persze csak retorikailag, amúgy fél nyolc már, de még így is szép, de hálisten már nem giccsesen szép), menjünk már, Józsi, nem neked kell vezetni, ne sürgess, igyunk majd valahol egy kávét és együnk valamit, menjünk, menjünk a nemzeti park felé, álljunk meg ott mondjuk valahol, miután átkelünk a komppal a Rhone-on, talán nem kérik el, talán nem kérik el az öt eurós révdíjat, de elkéri, de legalább mosolyog, de miért kérte el, de miért kérte el, de menjél már előre, de hogy ide is, de hogy itt is a kurva körforgalom (majd belinkelem hol van az a - itt, de itt még nincs meg a körforgalom), Salin-de-Giraud,

Jocót itt zárja be a csak franicául tudó pincérnő a klotyóba

boulangerie, bulanzserí, egy-egy szelet hagymás szardellás izé, egy-egy darab pain aux raisins, a legjobb, amit Franciahon adott a világnak (vagy hát saját maguknak, mert máshol nincs), jaj, de szeretem a mazsolát, nézd azt a hülyét, hogy lehet így beállni, nem tud kiállni a másik, jaj, hát állj el, eláll, nem ideges, Ön sem, én sem, Ön sem, én sem, a szardellás sem rossz, bonjour, bonjour, itt mindenki köszön, bon appétit, merci, gúnyolódnak, lehet itt enni?, lehet, kedves vidéki emberek, bonjour, bonapp, nyomás, nincs itt semmi, sétáljunk, rohad, menjünk tovább inkább, nemzeti parkban séta?, hol, a madárlesnél, legalábbis ilyen ház nálunk a Madárvártán van, csak ott nem ül öregasszony, itt ül, de semmi infó, német házaspár, csodaszép 16 éves forma lánnyal,

ez egy remek kép a családról, kiválóan használja Józsi a fókuszszűrőt, viszont itt még a 16 sem látszik, de esküszöm, volt annyi

akárcsak egy Onetti elbeszélésből, ebből talán erőszak lesz, de akkor el kellene tenni a két szülőt lábalól, de nézd, milyen hosszúak azok a combok, többnek kell lennie, Papa, van az 18 is, de persze, hogy nincs, nagyon nincs, követnek, gibt es einen weg da?, ne, gibt's keinen weg, haha, haha, szerintünk is bohózatba illő, hol vannak már azok a rohadt flamingók, tovább, kocsiba vissza, követjük őket, megállnak, nézik a táblát, németek, meggondolják, mi is, tíz másodperc alatt, most ők követnek, les, inkább pódiumszerű emelvény, megállunk, felmegyünk, kurva sok nád meg még sás is, megállnak, mi van ott, hát semmi, mi lenne, megnézik, semmi, mi már úton, megállunk, ott egy izé, gém, az ugyan nem, az flamingó, beszarok, sétáljunk, sétáljunk, ott már több is, egy toll a kiszáradt mederben, narancssárgaesetlegrózsaszín, na elég ebből, tovább, sóhegyek, itt nem véletlenül írja a könyv, hogy nyolcszázezer (ezt számmal szoktuk, 800 000) tonna sót nyernek ki évente, szép fehér, ott a lány megint, most már mosolyog persze, megnyalom a földet érintett ujjam, sós, persze, a földbe fúrt ujj, sós, mosolyog, anyáék is, na menjünk, itt már nem egy flamingó, egész csapat, repdesnek mindenfelé, beborítva az eget, menjünk a partig, nekem nincs kedvem, de menjünk, és akkor ott, a végtelen part, a lány már fürdik persze anyáékkal, kiváló a terep, sok lakókocsi, a fájó búcsú attól, ami nem is lehetett a tiéd, továbbra sem akarok frizbizni, nem szeretek, csak azzal a megfelelő súlyúval (a megbízhatóság jele), inkább sétáljunk, jó, sétálunk negyven percet, nem szűnnek a lakókocsik, szűnnek a lakók, bádogfalak, egymásba fordítva hat autó, kiskert, kisklozet, mi ez, nyaralók, lakóházaik, cigányélet, hippiélet, hihetetlen, ilyen még nem láttam, na fussun vissza, csak egy perccel maradok le vagy hárommal, a világítótorony, a másik oldalon, mi van, oda nem tudunk bemenni, naturalista (a modoros szó a nudistára), nem szeretik, hogy ha nézed, hogy minek nézed, amit, minek, jó olvasok inkább, jó együnk valamit, ekkora szar grillcsirkét, de legalább a bor normális, akkor tehát még egy pálinka a kocsiban, akkor tehát itt alszunk mégis, nincs elég kenyér a vacsorához, én ugyan nem kérek, akkor megesszük a kolbászt a weetabix-szel, jó szar, sebaj, paradicsom, olívaolaj, tonhalkonzerv, másik Shiraz (Pneiszl csúcsbor), jól elkergettem négy francia csajt, de hát fiatalok, de hát mekkora lúzer vagy, de hát nem tök mindegy, nem tudtak dönteni, melyik kettőjé legyünk, adieu, igyunk még, már megint mintha lenne löket bennünk, a csomagokon alszom a hátuljában, a sofőr az anyóson, igazán elrendezhettük volna, habár nem nekem fáj a mindenem másnap reggel, hanem neked, öcsém, a te ötleted volt, én akárhol elalszom, csak felfele ne kelljen sétálni, azért az a kite-os kurva jól csinálta tegnap, persze csak kezdő, de akkor is, na menjünk, ennyi volt a francia hon, ledurrantjuk az egészet autópályán vissza, Antibes-ban bemegyek a bankba, tényleg minden oké, tényleg, de akkor sem hiszem el még a kérdezéstek sem, 24 sör, 2,5 decis üvegecskék, végre wifi, karton rozé otthoniaknak, kaja, zőccség, gyümölcs, Józsi a parkolóautomatát felügyeli,

Józsi bűvöli az ájfónt - a kép Cannes-nál készült, de ott sűrű a bejegyzés, ide meg elfér

húzzunk innen, állítólag Èze felé vannak a legszebb öblök, a legrosszabbat fogjuk ki, legalább jól bekajálok, jól leégek, egy jó kávé az útra, a fiatalember nem jöhet be póló nélkül, éreztem, de nem szóltam, bocs, addig én nézem, hogy milyen rohadt meleg van, azért a tenger meg ezek a hegyek hűsítenek ám, na írd meg azokat a képeslapokat, menjünk, tankolás, nem is volt irtó drága, az ott lent megint Monaco, mit gondolsz, hogy lehet, hogy sem a franciák, sem az olaszok nem olvasztották be, nincs tisztességes adózás, azok már akkor is értették, hogy kell azt legálisan elkerülni, a kizsákmányolás egyik fellegvára, persze, hogy minden büdös rohadtgazdag ott van, emlékszel a helikopteres hajókra, igen, na persze az Abramovicsnak Antibes-ban is van egy olyan meg St. Tropez-ban meg mindenhol, na lépj rá, ez az út, ez még rondább, mint a felüljáró a Nyugatinál vagy a Keletinél, ez végigmegy, ez igen, bravó, viszont a belváros korrekt, láttad, hogy megnézett, téged nézett, nem, téged, áh, téged, nincs hajam, nekem sincs, vegyünk egy térképet, szerelmes vagy a térképekbe, egy térképet, ez tökéletes, három lány, trafikus és két barátnője, megeszik Jocót ketten a szemükkel, egyik talán engem is, ezek az olasz lányok pofátlanok, nekem kell lesütnöm a szemem?, a következő utcán is, mindenhol, laza hely, jó kis utcák, apám, ezek szűkek, oda nézz, biztos az urát várja abban az öltözékben, meg az összes többi hölgy is abban a hívogató pózban, inkább együnk valamit, együnk, itt nem szabadott volna halat rendelni, köszönöm az utólagos felvilágosítást, kedves lengyel tizenkét éve itt élő milf, de akkor sem fogok rád fanyalodni, ne röhögjél te meg, inkább igyunk még egy sört, a kisbolt, ott, az indiai eladók, üveget utcára nem szabad, de tessék, áttöltöm műanyag pohárba, mindenki így csinálja, az egész város az utcán iszik, elég hangosak, ezt látná a Tompa utcai polgármesterédesanya, áldom a szemeit, menjünk aludjunk, aludjunk, itt jó lesz, itt lehet a fa tövébe pössenteni, remélem, nem zaklatnak éjjel, nem teszik, már nem is tudom, hol kávézunk, az autópályán, forrósodik a levegő, olaszban melegebb van, jóval, Pisa, hol az a rohadt torony, igyunk itt is egy kávét, jó, jó szar a vécé, ezt ide nem volt érdemes cipelni, de neked elmondom, hogy nincs papír, viszont kifelé már láttam, van kéztörlő, nekem be kellett érnem, azzal, ami kiesett a zsebemből, habár jobban megvizsgálva, lehet, hogy nem is a zsebemből esett ki, nem érdekes most már, az érdekes, hogy ne legyen belépő meg parkolási díj, de van, hatvan cent egy óra, megdobom háromra, jé, van wifi, ingyenes, pont itt, a kocsitól öt méterre már nincs, megérte megvárni a vészvillogót kitéve, míg az a szerencsétleg elfogyasztotta a szendvicsét a volánnál, na nyomás be, kurva sok árus, ott a torony,

majdnem sikerült közrefogni

nincs belépő, dől, tartják a turisták a nagy semmit, támasztják a levegőt, Józsi bele is csap az egyik tenyerébe egy nagyot, jól van, ez mások szerint is vicces volt, na két fotó a közlekedési táblákkal (Józsi témája), két fotó markolókkal (enyém), menjünk, de egyre melegebb van, öt fokkal melegebb legalább, mindjárt ott vagyunk, szevasz Gergő, jó a kemping, nagyszerű, útlevél, parancsoljon, csak egy napot leszünk a háromszázhuszonhetes placcon, odanézz apám, hová valósi a kocsi, annyira nem szépek, mint akikkel a pályán hülyéskedtünk és vesztettük el őket betévedvén azok a hídon, de legalább a velencei önkiszolgáló kút olcsó volt, minek izgultam rajta, hogy benyeli az ötvenest, mondjuk, mert piszkosul elhagyatottnak tűnt a valami közepén, nem baj, nagyon jól áll nekik ez a fehérnemű, feszül a bőr a fenekén, de ha kocsija van, biztos több már, persze, ezek legalább húsz évesek, na majd este, na majd este, ejj, de rohadtul berúgtam, inkább alszok, ne aludjál, kelj fel, be kell menni, nem érted, nahát, mit is mondtál tegnap este, elaludtam, haragszom rád, elmentek a lányok ma, kurva szar ez a Jesoló, idősebb párok, még 16 éves formák is ritkaságszámban, a plebs paradicsoma, legyen német, olasz, keleti, átlagos vacsora, idióta pincér, de persze csak kedves akar lenni, és az a gazella a másik asztalnál, látszik, hogy leszarja a magánál hússzal idősebb fazont, na húzzunk, keljünk, menjünk haza, arrivederci.


2012. június 14., csütörtök

Labda ott

Felhivtam tegnap este a cegem, es eloadtam a problemat.

Ez az urge eleg dorzsolt lehet - de talan el is varhato, hiszen ez a munkaja, olvasni az embereket. Nem volt meglepodve egyaltalan, egybol a lehetseges opciokat sorolta.
Abban maradtunk, hogy elsore megprobal masik csapatot keriteni, amint lehet, mivel egy harom honap mulva esedekes valtast en nem tartottam elkepzelhetonek, addig itt nem birom ki.

Ez semmit nem jelent meg. Egyreszt, mivel a csapatvezetomtol is fugg, hogy fogadja mind az idozitest, mind a modjat, mert negativ reakcio eseten a valtas elvi lehetosege is kizart lenne, masfelol nagyon meglepne, ha talalnanak itt olyan poziciot, amelyet teljesen motivaltan tudnek vegezni. Egyszeruen tul sok reszre van darabolva a feladat, hogy barmelyik resze is onmagaban eleg erdekes legyen.

Gombokhoz nem nyulni, majmoknak enni adni.

Egy esely, ha van olyan csapat, ahol azt a reszt hegesztik, amit a gombok vezerelnek.

2012. június 1., péntek

Privát metódus tesztelése

Talán nem vagyok otthon a tesztelés világában annyira, mégis valamin megakadt a szemem.

Próbáltam lekövetni, hogy egy adott metódust mi hívja, és rohadtul privátnak tűnt...mégis protectedként szerepelt, amit elsőre nem értettem. Kiderült, hogy még egy helyről hívják a saját osztályán kívül: egy tesztből. 

Noha a teszteket nem ismerem, az objektum-orientáltság mellett annál inkább elkötelezett vagyok, így azt, hogy egy privát metódust egy teszt kedvéért protecteddé lazítsunk, egyszerűen elfogadhatatlannak tartom. Arról van szó ugyanis, hogy a teszt ugyanolyan package-ben volt, mint a tesztelt osztály, ezért elérte a protected metódust. Persze felmerül a kérdés (ami amúgy általában csak különböző kvízek vagy vizsgasorok közt), hogy miért protected akkor már, és miért nem default? Utóbbi kicsit korlátozóbb, körül-belül hasonló értelemmel, mint amit itt kihasználnak (sokan eleve vitatják a default viselkedés létjogosultságát). 
Az a tippen elsőre, hogy a felhasználó nem ismeri a pontos különbséget a "semmi" (default) és a protected közt. A másik az, hogy mivel a kezdő és a rossz fejlesztő nem ismeri a különbséget, ezért tudatos a döntés a protected mellett, nehogy összezavarják azokat - ez kicsit kicsavart magyarázat, keep it simple, akkor is, ha hülyeség.

Térjünk vissza azonban az eredeti kérdésre.

Lehet-e létjogosultsága annak, hogy közvetlenül egy teszt kedvéért módosítsuk a láthatóságot? Azaz: van-e a létjogosultsága a privát metódus tesztelésének?

Esetleg reflection-nel tesztelni, ha minden kötél szakad?

Próbáltam magamban érveket találni a fentiekre, de igazán erőset nem sikerült. A véleményem az, hogy egy ilyen eshetőség mindig a rossz tervezés eredménye, tehát minden privát metódust le kell tudni fedni az őt használó publikus interfész felől (bármelyik ágban is bújjon meg). 

Az adott esetben például az volt az érzésem, hogy a privát metódus hívása előtt egy csomó más hívás történik, ami csak az objektum megfelelő felinicializálása (talán felesleges az igekötő), felmockolása esetén fut le hibátlanul, és mivel ezt lusta volt a fejlesztő megtenni, egyszerűen átállította protectedre a vizsgált metódust, a többit meg leszarta.

Szóval - talán olvassa ezt legalább egy vagy két tesztelő, legalább egy vagy két fejlesztő - véleményeket szeretnék kérni a hozzászólások közt az egyáltalán nem költői kérdésekre.

Kösz :)