Skip navigation

Decided to move my blog to WordPress. Will be covering NoSql, Cloud, Spring, Jee and JSF there. Here is the link: http://ilya40umov.wordpress.com

In a past few years I've participated as an interviewer in many technical interviews.

 

 

Most of them were for engineering positions(In some cases I needed a new engineer for my team and most of the time I was simply asked to help to another PM/TL).

 

 

One of our colleagues has initially set a sort of tradition, which we used to follow, that we should ask a person, who was being interviewed, to write some code using a pen and a sheet of paper.

 

 

In most of the cases the guest was asked to write a program, which sorts an incoming array and explain the complexity of the chosen algorithm and provide some thoughts on making it better.

 

 

The most interesting thing is that quite a lot of people(especially junior/mid developer and even seniors sometimes) had a problem with accomplishing this task quickly. Some of them even didn't manage to write any workable solution at all.

 

 

In the cases when the solution was provided, the person usually had a problem telling pros and cons of the chosen algorithm and explaining the possible alternatives.

 

 

The guy, who initially invented asking this question, used to complain after the end of each interview that the invited engineer didn't write QuickSort algorithm and said nothing about the complicity(e.g. O(n^2) for bubble sort).

 

 

Well. You know how it is often said that you should never try to reinvent the wheel and must always use the provided by the platform libraries(e.g. Arrays.sort). I think this idea in many cases made some of the developers lazy(or even stupid) and now they are only capable of combining the existing components and tend to forget about the true programming.

 

 

I hope I'll never have to work in the same team with developers who can't write their own version of sorting algorithm without touching the computer/asking the Internet.

 

 

After a while I decided to refresh my memories in this area and created a simple project to implement several sorting algorithms. This move was also inspired by reading “Effective Java” by Joshua Bloch(I wanted to exercise some of the concepts from the book).


 

If you are interested, you can find my repo by the following link(I’ve also decided to play with GIT a little bit):

https://github.com/ilya40umov/array-sorting


 

BTW In my opinion, it’s not fair to ask someone to write QuickSort on the interview since this algorithms in not so trivial as it sounds.

I've never actually been working with JavaScript much.

With all those modern frameworks like JSF-based RichFaces and some GWT-based libraries(e.g. Vaadin) you don't actually need to do a lot of JavaScript coding.

And even if you do all these issues with cross-browser support and layout looking similar in all browsers tend to make you hating anything related to UI.

Thus you start being arrogant and ignorant to JavaScript, CSS, HTML features and focus on learning something solid like Java/JEE etc.

Of course if you had no options(e.g. you worked on a browser-based MMO game or a web portal with a rich UI) you would probably keep working with UI technologies, but in many cases you could still keep your heart cold about JavaScript and kept waiting for an oportunity to escape.

 

Recently a friend of mine has sent me a good link about JavaScript which I wished everyone who'd ever developed in JavaScript read.

 

Here it's by the way: A re-introduction to JavaScript (JS Tutorial)

 

Once I read it I also found several other extremely useful links from the same source:

 

Introduction to Object-Oriented JavaScript

 

JavaScript Guide

 

I think there are also some other sources on the Internet on this matter so that if you get interested you can find them as well.

 

The key point of this post is "JavaScript is not just some kind of buggy/ugly thing you have to write when you need to extend your web UI but rather a technologigy which is intended to be run on a host environment and has a lot of great and flexible features(its own paradigm of programming I would even say)".

Here is the series of arcticles by Mathieu Carbou about Reverse Ajax, Comet, WebSockets, Event-Driven Architecture etc. I think these articles can help anyone interested in this topic to get started:

 

Reverse Ajax, Part 1: Introduction to Comet

Reverse Ajax, Part 2: WebSockets

Reverse Ajax, Part 3: Web servers and Socket.IO

Reverse Ajax, Part 4: Atmosphere and CometD

Reverse Ajax, Part 5: Event-driven web development

The key point is that in the moder world everyone wants to develop more interactive application which should react almost instantly to the changes on the server side.

So the focus of Reverse Ajax technologies is adding an ability to send messages/notifications from the server side to the client side without waying for the user to push "Refresh" button in UI.

Previously on my blog I described a workaround in passing data to JSF bean method. http://community.jboss.org/people/ilya40umov/blog/2010/12/28/my-favourite-workarounds-dummymap-for-jsf-12

It's very useful when you need some simple transformation with data which you are going to display on a page or compare with something using EL.

But now I've already found and tested the best way to do it. This way is a creation of the custom EL function which performs your transformation. This solution is very elegant but it's now new. I found a lot of posts on the Internet dated 2006-... about this topic. But I just want to show you my solution and tell you what didn't work for me.

My environment consists of Jboss 5.1 + Facelets 1.1.15-B1 + JSF 1.2.

I have a tag library based on facelets in my project. It was done accordingly to http://www.ibm.com/developerworks/java/library/j-facelets/.

So at first I want to tell you what didn't work:

  • using of function declaration in my taglib.xml like it's shown below didn't get me any results

     <facelet-taglib>

         <function>

            <function-class>com.test.ElFunctions</function-class>

               <function-name>isInteger</function-name>

               <function-signature>boolean isInteger(java.lang.String)</function-signature>

         </function>

     </facelet-taglib>

  • I had to create a separated library for functions because when I tried to define my custom tags in the same file as library-class it didn't work either.

Now about how it works.

1) Declaring library in web.xml

     <context-param>

          <param-name>facelets.LIBRARIES</param-name>

          <param-value>/WEB-INF/facelets/tags/test.functions.taglib.xml</param-value>

     </context-param>

2) I created taglib file (test.functions.taglib.xml):

<?xml version="1.0"?>

<!DOCTYPE facelet-taglib PUBLIC

  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"

  "facelet-taglib_1_0.dtd">

<facelet-taglib>

          <library-class>com.test.FnLibrary</library-class>

</facelet-taglib>

3) I created FnLibrary.java

 

import java.lang.reflect.Method;

import java.lang.reflect.Modifier;

 

 

import com.sun.facelets.tag.AbstractTagLibrary;

 

 

public final class FnLibrary extends AbstractTagLibrary {

 

          public final static String NAMESPACE = "http://www.test.com/jsf/functions";

 

 

          public static final FnLibrary INSTANCE = new FnLibrary();

 

 

          public FnLibrary() {

                    super(NAMESPACE);

                    try {

                              Method[] methods = FunctionsLibrary.class.getMethods();

                              for (int i = 0; i < methods.length; i++) {

                                        if (Modifier.isStatic(methods[i].getModifiers())) {

                                                  this.addFunction(methods[i].getName(), methods[i]);

                                        }

                              }

                    } catch (Exception e) {

                              throw new RuntimeException(e);

                    }

          }

 

}

 

4) And I created FunctionsLibrary.java

 

public class FunctionsLibrary {

 

          public static boolean isInteger(String value) {

                    if (value != null) {

                              try {

                                        Integer.valueOf(value);

                                        return true;

                              } catch (NumberFormatException e) {

                                        //ignore

                              }

                    }

                    return false;

          }

}

 

For using this library you just need to define prefix in your root element xmlns:tf="http://www.test.com/jsf/functions" and then you can use it in EL expressions.

So #{tf:isInteger('345')} returns true. =)

 

P.S. I used the following link for my final solution. It's completely based on this source. I'm just wondering why other solutions didn't work.

http://seamframework.org/Documentation/CreatingCustomELFunctions

When I firstly tried EJB 3.0 in my applications I found that I need to write a log of EntityManager-like classes. They are very similar to DAO objects and each of they holds all possible operations for his entity. My app was full of similar lines of code. So I found some solutions on the Internet and combined them with my own thoughts. The following class is a result of several tries to implement the best solution:

 

 

package ccgproj.backend.rdbms.em;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import ccgproj.backend.exceptions.CreateException;
import ccgproj.backend.exceptions.DataStoreException;
import ccgproj.backend.exceptions.FinderException;
import ccgproj.backend.exceptions.RemoveException;
import ccgproj.backend.exceptions.UpdateException;
import ccgproj.backend.rdbms.entity.IEntity;
/**
* Class type: base class for entityManager EJB's<br/>
* <br/>
* Orders:<br/>
* 1) provides base methods for managing entity <br/>
* 2) provides protected methods for executing queries <br/>
*
* @author sorokoumov
*/
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public abstract class GenericManager<T extends IEntity> {
    /**
     * injected JPA entity manager
     */
    @PersistenceContext(unitName = "CCGProjectPersistenceUnit")
    private EntityManager em;
    /**
     * creates entity
     *
     * @param obj
     * @return
     * @throws CreateException
     */
    public T create(T obj) throws CreateException {
        try {
            em.persist(obj);
            return obj;
        } catch (Exception e) {
            throw new CreateException(e);
        }
    }
    /**
     * updates entity
     *
     * @param obj
     * @return
     * @throws UpdateException
     */
    public T update(T obj) throws UpdateException {
        try {
            obj = em.merge(obj);
            return obj;
        } catch (Exception e) {
            throw new UpdateException(e);
        }
    }
    /**
     * refreshes entity(this action completely resets a state of entity)
     * @param obj
     * @throws DataStoreException
     */
    public void refresh(T obj) throws DataStoreException {
        em.refresh(obj);
    }
    /**
     * removes entity but it refreshes it before.
     * Refreshing is required because entity could be detached/or composed out of transaction.
     * @param obj
     * @throws RemoveException
     */
    public void remove(T obj) throws RemoveException {
        try {
            em.refresh(obj);
            em.remove(obj);
        } catch (Exception e) {
            throw new RemoveException(e);
        }
    }
    /**
     * checks if entityManager contains this entity
     * @param obj
     * @return
     * @throws DataStoreException
     */
    public boolean contains(T obj) throws DataStoreException {
        try {
            return em.contains(obj);
        } catch (Exception e) {
            throw new DataStoreException(e);
        }
    }
    /**
     * detaches entity.
     * It's very useful when you need to apply some changes to entity within a transaction
     * but you don't want the container to call merge method because you want to perform a custom update to this entity.
     * @param obj
     * @throws DataStoreException
     */
    public void detach(T obj) throws DataStoreException {
        try {
            if (em.contains(obj)) {
                em.detach(obj);
            }
        } catch (Exception e) {
            throw new DataStoreException(e);
        }
    }
    /**
     * returns class of T
     * @return
     */
    @SuppressWarnings("unchecked")
    private Class<T> getEntityClass() {
        ParameterizedType ptype = (ParameterizedType) getClass().getGenericSuperclass();
        return (Class<T>) ptype.getActualTypeArguments()[0];
    }
    /**
     * finds entity ny PK
     * @param pk
     * @return
     * @throws FinderException
     */
    public T findByPrimaryKey(Object pk) throws FinderException {
        T obj = null;
        try {
            obj = em.find(getEntityClass(), pk);
        } catch (Exception e) {
            throw new FinderException(e);
        }
        if (obj == null) {
            throw new FinderException(getEntityClass().getName() + " with id "
                    + pk + " not found");
        }
        return obj;
    }
    /**
     * executes named query with a single result. Hence if result is not found or
     * it contains multiply entries method throws FinderExpection.
     * @param namedQuery
     * @param params
     * @return
     * @throws FinderException
     * @throws DataStoreException
     */
    protected Object executeQuerySingleResult(String namedQuery,
            Object... params) throws FinderException, DataStoreException {
        try {
            Query query = em.createNamedQuery(namedQuery);
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    query.setParameter(i + 1, params[i]);
                }
            }
            List<?> list = query.getResultList();
            if (list.size() != 1 || list.get(0) == null) {
                throw new FinderException("Multiply or no entries.");
            }
            return list.get(0);
        } catch (FinderException e) {
            throw e;
        } catch (Exception e) {
            throw new DataStoreException(e);
        }
    }
    /**
     * executes named query with multiply results
     * @param namedQuery
     * @param params
     * @return
     * @throws DataStoreException
     */
    protected List<?> executeQueryMultiplyResult(String namedQuery,
            Object... params) throws DataStoreException {
        try {
            Query query = em.createNamedQuery(namedQuery);
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    query.setParameter(i + 1, params[i]);
                }
            }
            return query.getResultList();
        } catch (Exception e) {
            throw new DataStoreException(e);
        }
    }
    /**
     * executes named query with multiply results.
     * This method has startPosition and maxResult parameters.
     * @param namedQuery
     * @param startPosition
     * @param maxResult
     * @param params
     * @return
     * @throws DataStoreException
     */
    protected List<?> executeQueryMultiplyResult(String namedQuery,
            Integer startPosition, Integer maxResult, Object... params)
            throws DataStoreException {
        try {
            Query query = em.createNamedQuery(namedQuery);
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    query.setParameter(i + 1, params[i]);
                }
            }
            if (startPosition != null) {
                query.setFirstResult(startPosition);
            }
            if (maxResult != null) {
                query.setMaxResults(maxResult);
            }
            List<?> list = query.getResultList();
            return list;
        } catch (Exception e) {
            throw new DataStoreException(e);
        }
    }
    /**
     * finds list of entities with named query. So that it helps not cast results to List<T> in other classes.
     * @param namedQuery
     * @param params
     * @return
     * @throws DataStoreException
     */
    @SuppressWarnings("unchecked")
    protected List<T> findObjectsList(String namedQuery, Object... params)
            throws DataStoreException {
        return (List<T>) executeQueryMultiplyResult(namedQuery, params);
    }
    /**
     * finds list of entities with named query. So that it helps not cast results to List<T> in other classes.
     * This method has startPosition and maxResult parameters.
     * @param namedQuery
     * @param startPosition
     * @param maxResult
     * @param params
     * @return
     * @throws DataStoreException
     */
    @SuppressWarnings("unchecked")
    protected List<T> findObjectsList(String namedQuery, Integer startPosition,
            Integer maxResult, Object... params) throws DataStoreException {
        return (List<T>) executeQueryMultiplyResult(namedQuery, startPosition,
                maxResult, params);
    }
    /**
     * finds a single object
     * @param namedQuery
     * @param params
     * @return
     * @throws FinderException
     * @throws DataStoreException
     */
    protected Object findSingleObject(String namedQuery, Object... params)
            throws FinderException, DataStoreException {
        try {
            return executeQuerySingleResult(namedQuery, params);
        } catch (FinderException e) {
            throw e;
        } catch (DataStoreException e) {
            throw e;
        } catch (Exception e) {
            throw new DataStoreException(e);
        }
    }
    /**
     * finds a single entity
     * @param namedQuery
     * @param params
     * @return
     * @throws FinderException
     * @throws DataStoreException
     */
    @SuppressWarnings("unchecked")
    protected T findSingleEntityObject(String namedQuery, Object... params)
            throws FinderException, DataStoreException {
        return (T) findSingleObject(namedQuery, params);
    }
    /**
     * executes named query with no result. like update/delete
     * @param namedQuery
     * @param params
     * @throws DataStoreException
     */
    protected void executeNoResultQuery(String namedQuery, Object... params)
            throws DataStoreException {
        try {
            Query query = em.createNamedQuery(namedQuery);
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    query.setParameter(i + 1, params[i]);
                }
            }
            query.executeUpdate();
        } catch (Exception e) {
            throw new DataStoreException(e);
        }
    }
    /**
     * executes EJB-QL/JPA-QL query and returns a list of objects
     * @param ejbQl
     * @param startPosition
     * @param maxResult
     * @param params
     * @return
     * @throws DataStoreException
     */
    protected List<?> executeEJBQLQueryMultiplyResult(String ejbQl,
            Integer startPosition, Integer maxResult, Object... params)
            throws DataStoreException {
        try {
            Query query = em.createQuery(ejbQl);
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    query.setParameter(i + 1, params[i]);
                }
            }
            if (startPosition != null) {
                query.setFirstResult(startPosition);
            }
            if (maxResult != null) {
                query.setMaxResults(maxResult);
            }
            List<?> list = query.getResultList();
            return list;
        } catch (Exception e) {
            throw new DataStoreException(e);
        }
    }
    /**
     * executes EJB-QL/JPA-QL query and returns a single object
     * @param ejbQl
     * @param params
     * @return
     * @throws FinderException
     * @throws DataStoreException
     */
    protected Object executeEJBQLQuerySingleResult(String ejbQl,
            Object... params) throws FinderException, DataStoreException {
        try {
            Query query = em.createQuery(ejbQl);
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    query.setParameter(i + 1, params[i]);
                }
            }
            List<?> list = query.getResultList();
            if (list.size() != 1 || list.get(0) == null) {
                throw new FinderException("Multiply or no entries.");
            }
            return list.get(0);
        } catch (Exception e) {
            throw new DataStoreException(e);
        }
    }
    public static interface ILoadMethod<T> {
        public List<T> find() throws DataStoreException;
    }
    /**
     * this method loads entries from DB using loader and updates all found entries, all entries which are not found would be deleted.<br/>
     * for comparing entities this method uses equals so don't forget to override it
     * @param elements
     * @param loader
     * @return result of operation
     */
    public List<T> executeSmartListUpdate(List<T> elements, ILoadMethod<T> loader) throws DataStoreException {
        List<T> result = new ArrayList<T>();
        List<T> loaded = loader.find();
        List<T> forDelete = new ArrayList<T>();
        for (T element : loaded) {
            if (!elements.contains(element)) {
                forDelete.add(element);
            }
        }
        for (T element : forDelete) {
            remove(element);
        }
        for (T element : elements) {
            if (loaded.contains(element)) {
                update(element);
            } else {
                create(element);
            }
        }
        return result;
    }
}

/**

* Class type: base class for entityManager EJB's<br/>

* <br/>

* Orders:<br/>

* 1) provides base methods for managing entity <br/>

* 2) provides protected methods for executing queries <br/>

*

* @author sorokoumov

*/

@TransactionManagement(TransactionManagementType.CONTAINER)

@TransactionAttribute(TransactionAttributeType.REQUIRED)

public abstract class GenericManager<T extends IEntity> {

 

    /**

     * injected JPA entity manager

     */

    @PersistenceContext(unitName = "unitName")

    private EntityManager em;

 

    /**

     * creates entity

     *

     * @param obj

     * @return

     * @throws CreateException

     */

    public T create(T obj) throws CreateException {

        try {

            em.persist(obj);

            return obj;

        } catch (Exception e) {

            throw new CreateException(e);

        }

    }

 

    /**

     * updates entity

     *

     * @param obj

     * @return

     * @throws UpdateException

     */

    public T update(T obj) throws UpdateException {

        try {

            obj = em.merge(obj);

            return obj;

        } catch (Exception e) {

            throw new UpdateException(e);

        }

    }

 

    /**

     * refreshes entity(this action completely resets a state of entity)

     * @param obj

     * @throws DataStoreException

     */

    public void refresh(T obj) throws DataStoreException {

        em.refresh(obj);

    }

 

    /**

     * removes entity but it refreshes it before.

     * Refreshing is required because entity could be detached/or composed out of transaction.

     * @param obj

     * @throws RemoveException

     */

    public void remove(T obj) throws RemoveException {

        try {

            em.refresh(obj);

            em.remove(obj);

        } catch (Exception e) {

            throw new RemoveException(e);

        }

    }

 

    /**

     * checks if entityManager contains this entity

     * @param obj

     * @return

     * @throws DataStoreException

     */

    public boolean contains(T obj) throws DataStoreException {

        try {

            return em.contains(obj);

        } catch (Exception e) {

            throw new DataStoreException(e);

        }

    }

 

    /**

     * detaches entity.

     * It's very useful when you need to apply some changes to entity within a transaction

     * but you don't want the container to call merge method because you want to perform a custom update to this entity.

     * @param obj

     * @throws DataStoreException

     */

    public void detach(T obj) throws DataStoreException {

        try {

            if (em.contains(obj)) {

                em.detach(obj);

            }

        } catch (Exception e) {

            throw new DataStoreException(e);

        }

    }

 

    /**

     * returns class of T

     * @return

     */

    @SuppressWarnings("unchecked")

    private Class<T> getEntityClass() {

        ParameterizedType ptype = (ParameterizedType) getClass().getGenericSuperclass();

        return (Class<T>) ptype.getActualTypeArguments()[0];

    }

 

    /**

     * finds entity ny PK

     * @param pk

     * @return

     * @throws FinderException

     */

    public T findByPrimaryKey(Object pk) throws FinderException {

        T obj = null;

        try {

            obj = em.find(getEntityClass(), pk);

        } catch (Exception e) {

            throw new FinderException(e);

        }

        if (obj == null) {

            throw new FinderException(getEntityClass().getName() + " with id "

                    + pk + " not found");

        }

        return obj;

    }

 

    /**

     * executes named query with a single result. Hence if result is not found or

     * it contains multiply entries method throws FinderExpection.

     * @param namedQuery

     * @param params

     * @return

     * @throws FinderException

     * @throws DataStoreException

     */

    protected Object executeQuerySingleResult(String namedQuery,

            Object... params) throws FinderException, DataStoreException {

        try {

            Query query = em.createNamedQuery(namedQuery);

            if (params != null) {

                for (int i = 0; i < params.length; i++) {

                    query.setParameter(i + 1, params[i]);

                }

            }

            List<?> list = query.getResultList();

            if (list.size() != 1 || list.get(0) == null) {

                throw new FinderException("Multiply or no entries.");

            }

            return list.get(0);

        } catch (FinderException e) {

            throw e;

        } catch (Exception e) {

            throw new DataStoreException(e);

        }

    }

 

    /**

     * executes named query with multiply results

     * @param namedQuery

     * @param params

     * @return

     * @throws DataStoreException

     */

    protected List<?> executeQueryMultiplyResult(String namedQuery,

            Object... params) throws DataStoreException {

        try {

            Query query = em.createNamedQuery(namedQuery);

            if (params != null) {

                for (int i = 0; i < params.length; i++) {

                    query.setParameter(i + 1, params[i]);

                }

            }

            return query.getResultList();

        } catch (Exception e) {

            throw new DataStoreException(e);

        }

    }

 

    /**

     * executes named query with multiply results.

     * This method has startPosition and maxResult parameters.

     * @param namedQuery

     * @param startPosition

     * @param maxResult

     * @param params

     * @return

     * @throws DataStoreException

     */

    protected List<?> executeQueryMultiplyResult(String namedQuery,

            Integer startPosition, Integer maxResult, Object... params)

            throws DataStoreException {

        try {

            Query query = em.createNamedQuery(namedQuery);

            if (params != null) {

                for (int i = 0; i < params.length; i++) {

                    query.setParameter(i + 1, params[i]);

                }

            }

            if (startPosition != null) {

                query.setFirstResult(startPosition);

            }

            if (maxResult != null) {

                query.setMaxResults(maxResult);

            }

            List<?> list = query.getResultList();

            return list;

        } catch (Exception e) {

            throw new DataStoreException(e);

        }

    }

 

    /**

     * finds list of entities with named query. So that it helps not cast results to List<T> in other classes.

     * @param namedQuery

     * @param params

     * @return

     * @throws DataStoreException

     */

    @SuppressWarnings("unchecked")

    protected List<T> findObjectsList(String namedQuery, Object... params)

            throws DataStoreException {

        return (List<T>) executeQueryMultiplyResult(namedQuery, params);

    }

 

    /**

     * finds list of entities with named query. So that it helps not cast results to List<T> in other classes.

     * This method has startPosition and maxResult parameters.

     * @param namedQuery

     * @param startPosition

     * @param maxResult

     * @param params

     * @return

     * @throws DataStoreException

     */

    @SuppressWarnings("unchecked")

    protected List<T> findObjectsList(String namedQuery, Integer startPosition,

            Integer maxResult, Object... params) throws DataStoreException {

        return (List<T>) executeQueryMultiplyResult(namedQuery, startPosition,

                maxResult, params);

    }

 

    /**

     * finds a single object

     * @param namedQuery

     * @param params

     * @return

     * @throws FinderException

     * @throws DataStoreException

     */

    protected Object findSingleObject(String namedQuery, Object... params)

            throws FinderException, DataStoreException {

        try {

            return executeQuerySingleResult(namedQuery, params);

        } catch (FinderException e) {

            throw e;

        } catch (DataStoreException e) {

            throw e;

        } catch (Exception e) {

            throw new DataStoreException(e);

        }

    }

 

    /**

     * finds a single entity

     * @param namedQuery

     * @param params

     * @return

     * @throws FinderException

     * @throws DataStoreException

     */

    @SuppressWarnings("unchecked")

    protected T findSingleEntityObject(String namedQuery, Object... params)

            throws FinderException, DataStoreException {

        return (T) findSingleObject(namedQuery, params);

    }

 

    /**

     * executes named query with no result. like update/delete

     * @param namedQuery

     * @param params

     * @throws DataStoreException

     */

    protected void executeNoResultQuery(String namedQuery, Object... params)

            throws DataStoreException {

        try {

            Query query = em.createNamedQuery(namedQuery);

            if (params != null) {

                for (int i = 0; i < params.length; i++) {

                    query.setParameter(i + 1, params[i]);

                }

            }

            query.executeUpdate();

        } catch (Exception e) {

            throw new DataStoreException(e);

        }

    }

 

    /**

     * executes EJB-QL/JPA-QL query and returns a list of objects

     * @param ejbQl

     * @param startPosition

     * @param maxResult

     * @param params

     * @return

     * @throws DataStoreException

     */

    protected List<?> executeEJBQLQueryMultiplyResult(String ejbQl,

            Integer startPosition, Integer maxResult, Object... params)

            throws DataStoreException {

        try {

            Query query = em.createQuery(ejbQl);

            if (params != null) {

                for (int i = 0; i < params.length; i++) {

                    query.setParameter(i + 1, params[i]);

                }

            }

            if (startPosition != null) {

                query.setFirstResult(startPosition);

            }

            if (maxResult != null) {

                query.setMaxResults(maxResult);

            }

            List<?> list = query.getResultList();

            return list;

        } catch (Exception e) {

            throw new DataStoreException(e);

        }

    }

 

    /**

     * executes EJB-QL/JPA-QL query and returns a single object

     * @param ejbQl

     * @param params

     * @return

     * @throws FinderException

     * @throws DataStoreException

     */

    protected Object executeEJBQLQuerySingleResult(String ejbQl,

            Object... params) throws FinderException, DataStoreException {

        try {

            Query query = em.createQuery(ejbQl);

            if (params != null) {

                for (int i = 0; i < params.length; i++) {

                    query.setParameter(i + 1, params[i]);

                }

            }

            List<?> list = query.getResultList();

            if (list.size() != 1 || list.get(0) == null) {

                throw new FinderException("Multiply or no entries.");

            }

            return list.get(0);

        } catch (Exception e) {

            throw new DataStoreException(e);

        }

    }

 

}

 

Some notes about GenericManager:
1) I created several exceptions which extend Exception class. I guess that every application should have its own set of exceptions.
2) I suppose that every method which finds something in DB and returns single result should throw FinderException instead of returning null.
3) Object... params is a very helpful way to pass unlimited count of parameters.
4) startPosition and maxResult could be null. In this case they are simply ignored by GenericManager.
5) some public methods like update/create etc. are automatically available in all childes as public methods. Thus you don't need to write them for every manager separately.
Simple usage sample on EJB 3.1(@LocalBean):

 

@Stateless
@LocalBean
public class UserManager extends GenericManager<User> {
    public List<User> findAllUsers(Integer start, Integer max)
            throws DataStoreException {
        return findObjectsList("findAllUsers", start, max);
    }
    public User findUserByLogin(String login) throws FinderException,
            DataStoreException {
        return findSingleEntityObject("findUserByLogin", login);
    }
}
I will appreciate any comments/suggestions about this article.

 

 

Thanks for your attention.
I didn't know anything about this workaround for a long time and now I even can't remember where I had finally read it. But anyway it can help you if you want to call some function on JSF page with parameter(or even with several parameters) when page is being rendered.
So let's imagine that you want to perform some simple transformation on data which you just got from a bean.
Most likely you want to write an expression like this:
#{myBean.performTransform(myBean.data)}
But this won't work in JSF 1.2. It will work in JSF 2.0 of course but what if you already have a giant application on JSF 1.2.
So finally I found a little bit strange but still very helpful trick. You should write a class which implements java.util.Map interface and you should leave all method except of get method empty. This get method should implement a transform you want to perform. And then you can create an instance of this class and use it in JSF EL on jsp pages. My own code is below:

I didn't know anything about this workaround for a long time and now I even can't remember where I had finally read it. But anyway it can help you if you want to call some function on JSF page with parameter(or even with several parameters) when page is being rendered.

So let's imagine that you want to perform some simple transformation on data which you just got from a bean.

Most likely you want to write an expression like this:

#{myBean.performTransform(myBean.data)}

But this won't work in JSF 1.2. It will work in JSF 2.0 of course but what if you already have a giant application on JSF 1.2.

So finally I found a little bit strange but still very helpful trick. You should write a class which implements java.util.Map interface and you should leave all method except of "T get(Object key)" method empty. This "T get(Object key)" method should implement a transform you want to perform. And then you can create an instance of this class and use it in JSF EL on jsp pages like this:

 

#{myBean.performTransform[myBean.data]}

 

My own code is below:

 

 

DummyMap.java:

 

 

import java.util.Collection;

import java.util.Map;

import java.util.Set;

 

public abstract class DummyMap<T> implements Map<String, T> {

 

    @Override

    public abstract T get(Object key);

 

    @Override

    public int size() {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public boolean isEmpty() {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public boolean containsKey(Object key) {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public boolean containsValue(Object value) {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public T put(String key, T value) {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public T remove(Object key) {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public void putAll(Map<? extends String, ? extends T> m) {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public void clear() {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public Set<String> keySet() {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public Collection<T> values() {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

    @Override

    public Set<Entry<String, T>> entrySet() {

        throw new UnsupportedOperationException("Not supported yet.");

    }

 

}

 

 

MyBean.java:

 

 

public class MyBean {

 

    private String data = "123";

 

    private DummyMap<String> performTransform = new DummyMap<String>() {

        @Override

        public String get(Object key) {

            if (key != null) {

                return "Hello " + key + "!";

            } else {

                return null;

            }

        }

    };

 

    public DummyMap<String> getPerformTransform() {

        return performTransform;

    }

 

    public void setPerformTransform(DummyMap<String> performTransform) {

        this.performTransform = performTransform;

    }

 

    public String getData() {

        return data;

    }

 

    public void setData(String data) {

        this.data = data;

    }

 

}

 

 

So this workaround does not looks right but it can help a lot especially when you have an iteration tag like h:dataTable and you want to perform some simple transfrom on data of current row. I also don't suggest anybody to use a complicated logic or access to DB in your get method either.

 

If someone has any other ideas or approaches for JSF 1.2 which can call functions with parameters from a jsp page, please, write it in comments.

 

P.S. I guess that the same is possible with custom EL functions but I've never seen articles about their creation.

I'm a J2EE developer and I have about 2,5 years of experience in developing enterprise applications. But recently I became a team leader in my company and that's why I decided that I should pay more attention on communication with people and exchange of experience and best practices. In this blog I'm going to raise topics which I want to discuss. I appreciate any comment and suggestion even if they would not be pleasant for me. I also appologize about my English. It's still not good enough but I promise to keep working on it. =)
These are some of the topics which I want to raise in this blog:
1) comparing of IDEs
2) JSF + Richfaces best practices, work arounds, and tricks
3) comparing of application servers
4) JPA, Hibernate, etc.
5) Improving of performance in J2EE
6) arhitecture of J2EE applications
I think that this list will be updated later. If you want to discuss something with me you can also write it in this topic's comments and I'll probably create a new article for it.

I'm a J2EE developer and I have about 3 years of experience in developing enterprise applications(I had a few years of developing smaller applications before it). But recently I became a team leader in my company and that's why I decided that I should pay more attention to communication with people and exchange of experience and best practices. In this blog I'm going to raise topics which I want to discuss. I appreciate any comments and suggestions even if they would not be pleasant for me. I also apologize about my English. It's still not good enough but I promise to keep working on it. =)

These are some of the topics which I want to raise in this blog:

1) comparing of IDEs

2) JSF + Richfaces best practices, work arounds, and tricks

3) comparing of application servers

4) JPA, Hibernate, etc.

5) Improving of performance in J2EE

6) arhitecture of J2EE applications

I think that this list will be updated later. If you want to discuss something with me you can also write it in this topic's comments and I'll probably create a new article for it.

Filter Blog

By date:
By tag: