Sunday, September 26, 2010

Developing a GWT Hosted on AppEngine

GWT

Using Eclipse with Google plugin:
  • to run application  locally: Google->Compile GWT (red toolbox toolbar icon) and run as Run As->Web Application

Wednesday, May 19, 2010

Flex with Cairngorm 2 - Popups Strategy

This post is a brief summary how we use Cairngorm 2 methodology for popups in Flex applications in the IT shop I work at:

  • Three files are created for each popup:
    • popup view
    • Cairngorm event to initiate showing of the popup
    • Cairngorm command to actually show the popup using PopupManager
  • Any data that needs to be passed to the popup is attached to the event.
  • When user closes the popup, the popup view simply removes itself from PopupManager.
  • The results of the popup, if any, are updated (can be done via data binding) in the ModelLocator, to which other controlls are bound as well, if needed.

Wednesday, May 12, 2010

Options for Java Middle-Tier of an RIA Application

Choice of Standard/Framework
Here's my best option or two for each area:
  • Persistence:

    • JPA. Use implementation-specific annotations only where unavoidable, and mark them in a way that will allow you to find all of them easily.
     
  • Transaction Management: EJB 3.1
  • Dependency Injection: EJB 3.1
  • Security: EJB 3.1
  • Exposing required web services:EJB 3.1
  • AOP: EJB 3.1 if their support for AOP is sufficient for you. Otherwise: Spring
  • Other:

    • Singletons: EJB 3.1
Providers
  • JPA: I use Hibernate, but the whole advantage of JPA is, that which provider you use is much less important than it used to be.
  • Application Server: Glassfish 3. It does support EJB 3.1.

Wednesday, April 28, 2010

Flex 3 and Flex 4 - Tips

  • When manually dispatching an event, using uiComponent.dispatchEvent(your-event), you need to add listener to the same component uiComponent. So, uiComponent.addEventListener(type,handler) will work, but uiAnyOtherComponent.addEventListener(type,handler) will not work.
  • The state changes-related transition effects have to correspond to the type of changes between the corresponding states.
    Example: I had a vertical group with two components. In State 1, both components show. In State2, Comp1 is not included. I set a Resize transition for Comp1 and a Move transition for Comp2. The effect was surprising: when state changed, Comp1 disappeared and appeared at the bottom of the screen. There it was re-sized. The right fix was to change Comp1: instead of includeIn=State1, I did height.State2=0. That did the trick.
  • Constraint-based layout is supported only in a container with BasicLayout. If you want to use it inside a VGroup, for example, you can put it inside a Group for which you don't specify any layout (BasicLayout is the default).

    Thursday, April 22, 2010

    Installing Samsung Printer ML-2510 on a Network Server under Win7

    • Go to: Control Panel > Hardware and Sound > Devices and Printers.
    • Click "Add a Printer" and in a new window: Click "Add a local printer".
    • Select "Create a new port" via radio buttons. Select "Standard TCP/IP Port" via dropdown. Click "Next".
    • Enter "192.168.0.2"  or whatever is your print server IP address via textbox "Hostname or IP Address". Modify "192.168.0.102" via textbox "Port Name" if desired. Unselect "Query the printer [...]" via checkbox.
    • Select custom settings and set:
      • Protocol LPR and Queue Name L1 and enable LPR Byte Counting.
    • Reach page "Install the print driver".
    • Select "Samsung" via scroll list "Manufacturer". Click "Windows Update" if "Samsung ML-2510 Series" does not appear in scroll list "Printers".
    • [Additional procedures may be needed to continue with printer addition]
    • Reach situation in previous step. Select "Samsung" and "Samsung ML-2510 Series". Click "Next".
    • [Additional procedures may be needed to complete printer addition]

    Monday, April 19, 2010

    Persistence Layer for Flex-and-Java Applications And The Like

    1. Introduction

    When architecting an RIA (aka Web 2.0) application, you have to decide how do you implement the persistence layer. Using the ORM is a standard nowadays, so it's given.  Question as to which ORM to use, got easier with strong acceptance of the Sun's JPA standard by the industry. But, how do you apply ORM in an RIA application is not a question with just a one obvious answer. On one side, the choice of the framework (and the architecture with it). This is presented in section 2. Section 3 presents another aspect of persistence layer: session management, that is how you actually use ORM to persist detached objects (detached, because they are received from outside of the application, namely from the client, for example a Flex client).

    2. ORM in an RIA Application

    Popular options are listed below. Each with advantages and disadvantages.

    2.1. Just-JPA Approach:
    • LCDS, BlazeDS or another Flex remoting framework
    • JPA (in general: ORM) on the server-side, with an object mapper like Dozer
    Pros and Cons:
    • Pro: Simple and a popular choice.
    • Con: Doesn't let you take advantage of ORM's lazy loading and lazy initialization.
      2.2. LCDS with Built-In Hibernate Adapter:

      This solution requires you to purchase a commercial heavy-duty Flex remoting framework Adobe LCDS (LiveCycle Data Services). If you go this way, to integrate it with persistence layer, you create a Hibernate assembler class on the server (Java) and point the LCDS destination to it, as described here.

      Pros and Cons:
      • Pro: (I believe) it takes advantage of lazy loading and initialization.
      • Cons: all of the persistence layer is implemented on the client which can lead to bigger/fatter client.
      • Cons: expense.
      • Cons: proprietary solution.
      2.3. BlazeDS with Gilead:

      Open source solution. Described in detail here.

      Pros and Cons:
      • Pro: open-source; no vendor lock-in.
      • Cons: unknown.
      2.4. GraniteDS:

      Provides a complete open-source solution. Described in a nutshell in comment to this article. More complete information, and a comparison with LCDS-with-Hibernate-assembler option, can be found in this article by the same person (as the comment), William Drai. This article has also more general, highly useful, background on the topic as a whole.

      Pros and Cons:
      • Pro: open-source; no vendor lock-in.
      • Cons: unknown
      3. Persisting Detached Objects

      The three most common applicable persistence design patterns are (as described by Hibernate documentation):
      • session per requestThe most common solution. A single Session and a single database transaction implement the processing of a particular request event. Do never use the session-per-operation anti-pattern.
      • session per conversationOnce persistent objects are considered detached during user think-time and have to be reattached to a new Session after they have been modified.
      • session-per-request-with-detached-objectRecommended. In this case a single Session has a bigger scope than a single database transaction and it might span several database transactions. Each request event is processed in a single database transaction, but flushing of the Session would be delayed until the end of the conversation and the last database transaction, to make the conversation atomic. The Session is held in disconnected state, with no open database connection, during user think-time.
      For another good article on this topic see this.

      3.1 More about Session-Per-Request Pattern

      Let's assume we have an application an RIA with stateless EJB's on the server side. Each request gets a new EntityManager injected. I suggest the following approach to implement session-per-request:
      • if we receive a new object, persist it using
            entityManager.persist(entity)
      • if we receive an object, that is already in the database, use
            entityManager.merge(entity)
      There is one narrow case, when this wouldn't work as expected: when we have a bidirectional association between Invoice and InvoiceDetail and we receive and invoiceDetail with the field invoice set to null. If we apply the method as above, the merge() will reset the invoice in invoiceDetail to null, while the field invoiceDetails in invoice object will continue pointing to invoiceDetail. However, I consider this not a practical case.

      4. Conclusion
      So, a simple starting point that I recommend for your RIA application is to use just JPA with a session-per-request persistence pattern. It can be as simple as:

      JpaDao {
        public void persist(E entity) {
          if (entity.getId() == null) {
            entityManager.persist(entity);
          } else {
            entityManager.merge(entity);
          }
        }
      }
      as suggested by Marcell Manfrin (in a comment).

      4. My Recommended Solution

      • Use JPA with an ORM provider of your own. 
      • Use only JPA annotations and avoid using native provider's annotations. If you have to use a provider's native application, mark it in the code in an easy to discover way.
      • Use session-per-request approach with object mapper like Dozer.
      • Unless domain model is very simple and used only in CRUD-like way, use DTO objects to transfer data between client and server (article).

        • Question: use simple domain objects with public fields?
      • Use service facade layer to:

        • manage session-per-request
        • map domain to/from DTO objects
        • isolate the client from the server
        • provide an lightweight API for the client rather than exposing the client to a complex domain model.