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
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:
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:
<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>
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:
/**
* 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);
}
}
}
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 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.