Tuesday, September 8, 2015

Màquines d'estat en JAVA

Gestionar els estats dels objectes en un entorn multi-thread, orientat a events, és complexe. Especialment si el mateix event pot provocar diferents accions depenent de l'estat sobre el que s'aplica.

Potser si parlem d'un problema en concret resultarà més fàcil comprendre la problemàtica. Vaig començar a enfrontar-me a aquest repte quan desenvolupava protocols en temps real per a la transmissió de veu. En concret, si miren la RFC sobre SIP, https://www.ietf.org/rfc/rfc3261.txt, una transacció servidor de SIP INVITE estaria descrita per:


                               |INVITE
                               |pass INV to TU
            INVITE             V send 100 if TU won't in 200ms
            send response+-----------+
                +--------|           |--------+101-199 from TU
                |        | Proceeding|        |send response
                +------->|           |<-------+
                         |           |          Transport Err.
                         |           |          Inform TU
                         |           |--------------->+
                         +-----------+                |
            300-699 from TU |     |2xx from TU        |
            send response   |     |send response      |
                            |     +------------------>+
                            |                         |
            INVITE          V          Timer G fires  |
            send response+-----------+ send response  |
                +--------|           |--------+       |
                |        | Completed |        |       |
                +------->|           |<-------+       |
                         +-----------+                |
                            |     |                   |
                        ACK |     |                   |
                        -   |     +------------------>+
                            |        Timer H fires    |
                            V        or Transport Err.|
                         +-----------+  Inform TU     |
                         |           |                |
                         | Confirmed |                |
                         |           |                |
                         +-----------+                |
                               |                      |
                               |Timer I fires         |
                               |-                     |
                               |                      |
                               V                      |
                         +-----------+                |
                         |           |                |
                         | Terminated|<---------------+
                         |           |
                         +-----------+

O bé dones amb una manera senzilla d'implementar aquest problema o acabaràs tenint codi difícil d'escriure, mantenir, propens a errors, dificil de testejar i impossible de tracejar. T'adonaràs que estàs en aquesta situació si téns un munt de if/elsesynchronized i t'has passat els últims 2 dies intentant entendre perquè la teva aplicació ha arribat a un estat concret que no esperaves.

Si t'has trobat en algun moment en aquesta situació, hauries de fer un cop d'ull a la meva llibreria https://bitbucket.org/xferro/sicoris-statemachine . Fins i tot, hi ha un SNAPSHOT disponible en cas que vulguis començar a provar-la.

Qualsevol comentari és benvingut. Espero que ho gaudiu!

Monday, September 7, 2015

Máquinas de estado para JAVA

Manejar los estados de los objetos en un entorno multi-thread, orientado a eventos, es duro. Especialmente si este evento puede provocar diferentes acciones dependiendo del estado sobre el que se aplique.

Quizás sea más fácil entenderlo con un problema concreto. Empecé a pensar sobre este problema cuando desarrollaba protocolos en tiempo real para voz. En concreto, si miramos la RFC sobre SIP https://www.ietf.org/rfc/rfc3261.txt, una A SIP INVITE server transaction tendría una pinta como sigue:


                               |INVITE
                               |pass INV to TU
            INVITE             V send 100 if TU won't in 200ms
            send response+-----------+
                +--------|           |--------+101-199 from TU
                |        | Proceeding|        |send response
                +------->|           |<-------+
                         |           |          Transport Err.
                         |           |          Inform TU
                         |           |--------------->+
                         +-----------+                |
            300-699 from TU |     |2xx from TU        |
            send response   |     |send response      |
                            |     +------------------>+
                            |                         |
            INVITE          V          Timer G fires  |
            send response+-----------+ send response  |
                +--------|           |--------+       |
                |        | Completed |        |       |
                +------->|           |<-------+       |
                         +-----------+                |
                            |     |                   |
                        ACK |     |                   |
                        -   |     +------------------>+
                            |        Timer H fires    |
                            V        or Transport Err.|
                         +-----------+  Inform TU     |
                         |           |                |
                         | Confirmed |                |
                         |           |                |
                         +-----------+                |
                               |                      |
                               |Timer I fires         |
                               |-                     |
                               |                      |
                               V                      |
                         +-----------+                |
                         |           |                |
                         | Terminated|<---------------+
                         |           |
                         +-----------+

Si no das con una solución fácil para implementar esta máquina de estados, acabarás teniendo un código: difícil de escribir, difícil de mantener, error-prone, difícil de probar y imposible de tracear. El signo que estás en una situación similar es que tienes un montón de if/elsesynchronized y y te has pasado 2 días intentando encontrar cómo has podido entrar en un estado que no tenías previsto.

Por tanto, si te has encontrado con este problema, deberías mirar mi solución. Acabo de finalizar una nueva iteración sobre el código y estoy muy satisfecho del resultado: https://bitbucket.org/xferro/sicoris-statemachine . Hay un SNAPSHOT disponible si quieres empezar a probar.

Cualquier comentario es bienvenido! Espero que lo disfrutéis!

State machines for Java

Managing object states for multi-threaded applications is hard. Especially, when this state can transition to another state depending on multiple events. 

I started thinking about this problem when implementing SIP protocol solutions. A SIP INVITE server transaction would look like:

                               |INVITE
                               |pass INV to TU
            INVITE             V send 100 if TU won't in 200ms
            send response+-----------+
                +--------|           |--------+101-199 from TU
                |        | Proceeding|        |send response
                +------->|           |<-------+
                         |           |          Transport Err.
                         |           |          Inform TU
                         |           |--------------->+
                         +-----------+                |
            300-699 from TU |     |2xx from TU        |
            send response   |     |send response      |
                            |     +------------------>+
                            |                         |
            INVITE          V          Timer G fires  |
            send response+-----------+ send response  |
                +--------|           |--------+       |
                |        | Completed |        |       |
                +------->|           |<-------+       |
                         +-----------+                |
                            |     |                   |
                        ACK |     |                   |
                        -   |     +------------------>+
                            |        Timer H fires    |
                            V        or Transport Err.|
                         +-----------+  Inform TU     |
                         |           |                |
                         | Confirmed |                |
                         |           |                |
                         +-----------+                |
                               |                      |
                               |Timer I fires         |
                               |-                     |
                               |                      |
                               V                      |
                         +-----------+                |
                         |           |                |
                         | Terminated|<---------------+
                         |           |
                         +-----------+

If you don’t think of an easy approach to representing/coding these state machines, you will end up having something: difficult to write, error prone, difficult to test and impossible to trace. The main sign that you are doing it wrong is when your code is full of if/else, synchronized blocks and you had to debug for 2d to find out how the hell you ended up in such an unexpected state.

So, if you happen to have to manage complex state objects, you should take a look to my library. I just finished a new iteration to the code and. Much happier than ever with it: https://bitbucket.org/xferro/sicoris-statemachine . There's already a SNAPSHOT version available, so you can use it already.


Any feedback is more than welcome!

Sunday, September 6, 2015

Better JDBC Prepared Statements?

After using PreparedStatements for a while, you understand how painful it is maintaining SQL queries. Setting values by position is error-prone and tough.
Let's imagine a query that you want to check multiple columns against the same value:
SELECT * FROM Table WHERE a > ? AND b < ? AND c == ?
You will need to have the following code in place:
int THE_VALUE = 12345;
stmt.setInt(1, THE_VALUE);
stmt.setInt(2, THE_VALUE);
stmt.setInt(3, THE_VALUE);
Just imagine that you need to refactor the query such as the new values don't have nothing to do with THE_VALUE. The query could look like this:
SELECT * FROM Table WHERE (a > ? OR ? ) AND (b < ? OR ?) AND c == ?
You'd need to refactor your previous query such as:
int THE_VALUE = 12345;
boolean ANOTHER_VALUE = false;
stmt.setInt(1, THE_VALUE);
stmt.setInt(3, THE_VALUE);
stmt.setInt(5, THE_VALUE);
stmt.setBoolean(2, ANOTHER_VALUE);
stmt.setBoolean(4, ANOTHER_VALUE);
Not sure what you think about, but having to count question marks in a query to make things work never looked very attractive to me. I think we could be smarter than that

So what?

Why not having something like:
SELECT * FROM Table WHERE a > @{startDate} AND b < @{startDate} AND C = @{startDate}
and code like:
int THE_VALUE = 12345;
smartStatement.setInt("startDate", THE_VALUE);
The second approach is not impacted by any refactoring and it's less error prone. So, this small library tackles this problem with a very simplistic approach.

The approach

The library is very compact and simple. It is responsible for parsing the sql query and populating prepared statement values, but nothing more. So, creation of the prepared statement itself is not part of this library. I wanted to avoid over-engineered wrappers for such a small problem

What is not supported?

Do not use parametrized values in the queries. It might break the parsing logic. So something like this will break:
String sql = "SELECT * FROM MY_STRINGS WHERE str = \"a string containing weird stuff: ${else}\" AND id = ${id}";
Use the following instead:
String weird = "a string containing weird stuff: ${else}";
String sql = "SELECT * FROM MY_STRINGS WHERE str = ${weird} AND id = ${id}";
smartStatement.setString(stmt, "weird", weird);
smartStatement.setString(stmt, "id", "WTF");

That's brilliant. Where can I find it?

Check my sicoris-jdbc bickbucket repo . Comment it, fork it, use it. Any feedback is more than welcome.

State machines in JS

You can read in previous blog posts the reasoning behind state machines: they simplify and unify the way we define states and transitions i...