JPA and stored procedures

In a majority number of cases the Java-Persistence API (JPA) to create/load/update entities cover all your needs. But sometimes you need to do something special inside the DB with help of stored-procedures. The good thing about JPA is that you still can use it to call the stored procedures and get the results back. Here is two cases of using it

  1. execute the stored-procedure and get the results back as Entity
  2. execute stored procedure and get the result back as non-entity (for example set of name-value pairs)

For the 1-st case you need to define the stored procedure in DB (syntax depends on DB, I’ll use the Postgre-SQL syntax)
In the code example below I’ll show how to create a new entity using the call to the stored-procedure. It solve the real problem of how to generate unique-record in DB. If we’ll try to use the standard JPA API we may end up with the code like that

public UniqueCode generateUniqueCode(int length, String prefix) {
do {
    String code = generateRandomString(length, prefix);
    if  ( notExistsInDB() // call to entityManager to check if such code exists) {
        UniqueCode code = new UniqueCode(code);
        entityManager.persist(code);
        return code;
    }
} while(true);
//no way to get to that point
return null;
}

So, at least 2 calls to DB (+1 for each loop cycle). Quite non-optimal, so why not do that with a single call to DB ?
Just in case – no need to inspect SQL code example below

DROP TYPE IF EXISTS unique_code_result CASCADE ;

-- we define the result-type of returned data (postgre need a type to be returned, it can't return RECORD)
CREATE TYPE unique_code_result AS (pk bigint, code character varying);

-- call generate_unique_code_on_table to generate unique value, insert it in the table
-- AND return the result of INSERT command as "unique_code_result" type
CREATE OR REPLACE FUNCTION generate_unique_code(length integer, prefix varchar)
RETURNS unique_code_result AS
$BODY$
DECLARE
 new_record unique_code_result;
BEGIN

  INSERT INTO unique_code (pk, code) VALUES
    (nextVal('unique_code_s'), generate_unique_code_on_table('unique_code', 'code', length, prefix))
  RETURNING pk, code INTO new_record;

RETURN new_record;

END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

-- generate_unique_code_on_table generates the UNIQUE column-value string for the "unique_column" on the table "table_name".
-- to implement that it generate the random string in the cycle and check if it is already exists by SQL request
-- If it doesn't exists - the value is returned, otherwise it generate next random value and check it
CREATE OR REPLACE FUNCTION generate_unique_code_on_table(table_name varchar, unique_column varchar, code_length integer, prefix varchar)
  RETURNS varchar AS
$BODY$
DECLARE
    select_request varchar;
    result VARCHAR;
    unique_code_key bigint;
BEGIN
    select_request = 'SELECT pk FROM ' || table_name || ' WHERE ' || unique_column || ' = $1';
    LOOP
        result := random_string(code_length);
        IF (prefix IS NOT NULL) THEN
	   result := prefix || result;
        END IF;

        EXECUTE select_request INTO unique_code_key USING result;
        IF NOT FOUND THEN
            RETURN result;
        END IF;
    END LOOP;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

Sorry for that long DB code, I want to show the real-life problem solution, not just plain INSERT.
Now, let’s call it from the JPA. In our example we generate and insert new record into the “unique_code” table. Let’s define that entity and required JPA annotations to call the stored procedure.

import javax.persistence.*;

@Entity
//result-type mapping used by native-query call
@SqlResultSetMapping(name = "UniqueCode.implicit", entities = {
        @EntityResult(entityClass = UniqueCode.class)
    }
)
@NamedNativeQueries({
        @NamedNativeQuery(name = "UniqueCode.generateNew",
                query = "select * from generate_unique_code (:length, :prefix)",
                resultSetMapping = "UniqueCode.implicit")
    }
)
@Table(name = "unique_code")
public class UniqueCode {

    @Id
    private Long pk;

    @Column(unique = true)
    private String code;
}

Now let’s call the Native-Query to generate the UniqueCode

        Query query = entityManager.createNamedQuery("UniqueCode.generateNew")
                .setParameter("length", length)
                .setParameter("prefix", prefix != null ? prefix : "");

        return (UniqueCode) query.getSingleResult();

That’s it! This call will return us new Entity which already exists in DB and can be used by other entities. Please note that we have to pass the empty-string (not null) as “prefix”, since DB will not be able to find corresponding db-procedure by signature if we’ll pass NULL.

It’s too much code already here, so I’ll show the 2-nd case “using native-query to return non-entities” in the next post.

Tagged with: , , , , , , , , , ,
Posted in Software Development, Tips and Tricks

TinyMCE 4 Spellchecker integration

TinyMCE is on it’s way to release new major update to 4.0. You may want to see a demo for a quick highlights of updates.

Well, I just realized that I’m writing this post in TinyMCE 3.5.8. 4.0 it is still in beta stage but probably we’ll see the upgrades to 4.0 in a few months after it will have final release.

Anyway, while doing updates to JSpellChecker (see below for a list) and developing the “usage example” project, I downloaded latest TinyMCE 4.0 release and was surprised by the error’s I see after trying to perform spellcheck. The thing is that TinyMCE 4.0 spellchecker plugin has a lot of updates and actually now it’s using completely different request structure than before (in 3.x). There is no docs yet which document the new spellchecker request structure, so I did investigation of requests in java debug and in Chrome developer console.

The good news about new spellchecker API is that it seems to be more optimal, since it execute only one request in which it sends words he want to check and expect the suggestions back (for all words) for misspelled words. So, user who use editor will be able to see suggestions right after he got response. Not sure how that will impact the server-side of spellchecker, but generally I think that algorithms could be optimized and suggestions to all words could be retrieved faster (since dictionaries/indexes are already loaded at the moment we look for misspelled words). At least number of potential requests to server will be much lower.

The bad news (on the moment) is that only one language is supported on the moment (spellchecker plugin always pass “lang”=”en”). There is a bug filled and I believe it will be fixed before final release. But you are welcome to vote for it!

TinyMCE site does not provide documentation on request/response structure for the new spellchecker API (actually it does not provide it for previous version too). Information below is a result of reverse engineering of new spellchecker plugin code.
Well, so the request structure is updated and now only one request is done by spellchecker plugin.
See example spellchecker request/response comparison table below:

Before TinyMCE 4.0 Since TinyMCE 4.0

“checkWords” request

Check the list of words passed as a second argument of the “params” array. First argument of the params array, define the “language”

Example request
{
"method" : "checkWords",
"params" : [ "en-us", ["usa","cawboy", "apple"] ]
}
Example Response
"id":null,
"result":["cawboy"],
"error":null}

“spellcheck” request

It is done by a single request/response now. “params” is now JsonObject not JsonArray and that make request more structured

Example request
{
"id"  : ${request-id},
"method" : "spellcheck",
"params" : {
 "lang": "en-us", 
 "words": ["usa","cawboy", "apple", "blablabla"] 
}
}
Example Response

The “result” will contain mappings where key is misspelled word and value is suggestion list for it. It also may return empty suggestion list for a word and that will mark it as “misspelled”

{
"id":"${request-id}",
"result": {
  "cawboy" : ["cowboy"],
  "Guugli" : ["Google"],
  "blablabla" : []
 }
}

“getWordSuggestions” request

Get suggestion for single word, passed as the 2-nd element in the “params” array

Example request
{
"method" : "getWordSuggestions",
"params" : [ "en-us", "Guugli" ]
}
Example Response
{"id":null,
"result":["Google"],
"error":null
}

Btw, the JspellChecker code is updated to support TinyMCE 4.0 request/response format. It also contains other refactorings, updates and fixes which I will cover in the next post

Tagged with: , , , , , , , , , , , , , ,
Posted in Software Development

Manage server throughput for large downloads

Manage server throughput for large downloads

Initially I want to explore the solutions to implement Servlet/OutputStream with limited throughput in order to limit single download to some bandwidth.

It looks to be a perfect article which describe the way to distribute/manage server resources for large downloads.

http://nurkiewicz.blogspot.com/2011/03/tenfold-increase-in-server-throughput.html
It help to address a lot of issues, like:

  • some clients might be more privileged, having bigger or no limit at all,
  • some might be black listed, resulting in connection rejection or very low throughput
  • banning IPs, requiring authentication, cookie/user agent verification, etc.
  • we might try to correlate concurrent requests coming from the same client and use the same bucket for all of them to avoid cheating by opening several connections. We might also reject subsequent connections
  • and much more…
Tagged with: , , , , ,
Posted in Software Development, Tips and Tricks

IcePush integration to web-application

Push notifications are fast as Running Flash
In one of the previous post I show an example of how a4j-push and a4j-poll were used together. It help to solve several things and optimize code/requests a bit. But in reality it was not “real” push – it just execute periodic lightweight requests (ping server) and asks him – “do you have something new for me ?”. It has serious cons:

  • number of requests to server is linearly depends on the number of browser windows opened, so more simultaneous users we have connected to the server – the higher loading it will have. So, actually server can be just “overloaded” by that simple requests
  • with regards to previous point we have to increase the period between requests (to make less impact on the server) – but it is not good for user experience, since it will see the updates with a larger delay

What I expect from Push is that server itself initiate the push-notification to the client. So it does that right at the moment he have to say something new to the client. There is no need to say that such server-to-client communication open a lot of great features and possibilities to web apps.
Here is the diagram from the IcePush docs

It probably not that visible, but in short – “It works great”. IcePush client (javascript) send the list of subscribed topics he want to listen, server genberate the unique ID for him, after that client establish the connection with the server which listen for response from server. Server will notify the client once he will have notifications to send to him. Client call the callback function in which you may do anything (you may call any javascript function as well the a4j:jsFunction if you want to do something through JSF)

As a result, the client browser will be notified right after the event will occur on the server. It will be immediately pushed to the client and after that client is free to do anything he want to react to the notification.

The good thing is that it’s fairly easy to integrate IcePush technology with existent java-web application. The requirement here is just to have a servlet container.
In my case it was existent Richfaces/Seam-2/JSF application (I was afraid that IcePush may conflict with Richfaces, but it is not the case, IcePush can be integrated completely transparent to the JSF/Seam application, since it integrates on Servlet level).
IcePush has a number of ways to integrate, but I’ve chooses the jQuery Integration
You can find all the necessary information about IcePush integration here. I will show the example of integration of IcePush with existent web-application (Seam/Richfaces). I think the integration could be the same for GWT or any other app which is deployed in the Servlet-Container.

  1. Downloaded jQuery integration package
  2. Added the icepush.jar to the WEB-INF/lib
  3. Added the following definition to web.xml
        <servlet>
            <servlet-name>icepush</servlet-name>
            <servlet-class>org.icepush.servlet.ICEpushServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>icepush</servlet-name>
            <url-pattern>*.icepush</url-pattern>
        </servlet-mapping>
    
  4. on the web-page initialized the IcePush with
    //loaded required scripts
            <script type="text/javascript" src="#{request.contextPath}/code.icepush"></script>
            <script type="text/javascript" src="#{request.contextPath}/js/icepush/jquery.icepush.js"></script>
    //initialized the icepush client
        <script type="text/javascript">
            var myPushNotificationCallback = function(){
               //do something on push callback. 
               //it may be ajax request to the server based on jQuery-ajax or a4j:jsFunction, whatever
               //for simplicity I will just call alert
               alert("Push notification arrived");
            }
            jQuery(document).ready(function () {
                //set the uriPrefix so icepush will make requests to the correct URL
                ice.push.configuration.uriPrefix = '#{baseAppPath}/';
                //register the icepush client, based on the user-primary-key
                jQuery.push.listenToGroup("myPushGroup_UsR_#{loggedInUser.pk}", myPushNotificationCallback);
            });
        </script>
    
    
  5. On the server side call the IcePush in the places I want to send notification (as a reaction to some event)
    We can call method pushToUserList directly, but I wrapped it so it become asynchronous call, so it don’t slow-down the http-request processing (it may send notifications to several clients and as long it is network operation, it’s may cause a significant delay)

    @Name("pushAsyncExecutor")
    @Scope(ScopeType.APPLICATION)
    public class PushAsyncExecutor implements Serializable {
    
        private static Log log = Logging.getLog(PushAsyncExecutor.class);
    
        @Asynchronous
        @SuppressWarnings("unused")
        public QuartzTriggerHandle  pushToUserList (@Expiration Date when,
                                                    String pushGroup, Collection<Long> userIds) {
            pushToUserList(pushGroup, userIds);
            return null;
        }
    
        public static void pushToUserList(String pushGroup, Collection<Long> userIds) {
            log.trace("Started pushToUserListImpl");
            try {
                PushContext pushContext = PushContext.getInstance(SeamComponentFactory.getServletContext());
                for (Long userId : userIds) {
                    pushContext.push(getUserNotificationGroupName(pushGroup, userId));
                }
            } catch (Throwable ex){
                log.error("Failed to push updates", ex);
            }
            log.trace("Finished pushToUserListImpl");
        }
    
        /**
         * this method generate the push-id for the userId and "pushGroup"
         */
        private static String getUserNotificationGroupName(String pushGroup, Long userId) {
            return new StringBuilder(pushGroup.length() + 16).append(pushGroup).append("_UsR_").append(userId).toString();
        }
    }
    
Tagged with: , , , , , , , , , , ,
Posted in Software Development, Tips and Tricks

How to avoid primary page conversation timeout on background requests in Seam. Hacking around Seam request lifecycle

Sometimes it's better to avoid something. Avoid can be a solutionIt will be not easy to read and understand this article, so please remember that you always have a choice to not read it 🙂
So,.. in our app we have few background processes on the page which are periodically ping server and update some page parts. Now I think this is not the greatest approach and we should use a real PUSH technology instead of periodic ping in every place where it is possible, but anyway. Our problem was that those requests (if they were handled by Seam Context-Filter) may cause our conversation (the page which user open in the browser) to be destroyed because of conversation timeout. And it really doesn’t work for us, since that really “secondary” requests may kill our primary conversation (especially if we have several browser windows opened)
So, to summarize the problem – “periodic seam requests (ajax requests) cause the destroying of the conversation”, so, if user don’t do any activity on the page during the conversation timeout – the next his action show the “Conversation timed out” message.

Partial solution here could be not use Seam ContextFilter for that requests, but in that case we couldn’t use our Seam components (so it don’t work for us)
The better solution (I think) – is to “Avoid timing-out the conversation in our background requests”. It is what will be described below. However the Much Better Solution would be also “Avoiding the background periodic requests by using a real push approach” – like it is shown in the IcePush integration post. But that not always work, but definitely preferable solution.
So, the workaround for us was to establish Seam environment for the request but don’t cause the the same environment as it is done in the org.jboss.seam.web.ContextFilter but don’t call the Manager.conversationTimeout()

Finally solution looks like 2 classes (created from Seam ContextFilter and ContextualHttpServletRequest)
pretty simple ContextFilterWithoutTimeout (it just create and run ContextualHttpServletRequestWOTimeout)

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import org.jboss.seam.web.AbstractFilter;

public class ContextFilterWithoutTimeout extends AbstractFilter {
   public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
       throws IOException, ServletException
   {
      new ContextualHttpServletRequestWOTimeout( (HttpServletRequest) request )
      {
         @Override
         public void process() throws ServletException, IOException
         {
            chain.doFilter(request, response);
         }
      }.run();
   }
}

and the ContextualHttpServletRequestWOTimeout which is a copy of ContextualHttpServletRequest with commented call to
// Manager.instance().endRequest( new ServletRequestSessionMap(request) );
so it doesn’t call the touchConversationStack() and Manager.instance().conversationTimeout(session);
as the result our request don’t update anything in the conversation stack and don’t cause the timing-out of conversations
“destroyConversation( conversationEntry.getId(), session );”
it doesn’t mean that conversations will not be timed out – they will, but they will do it as a result of primary user request (or request which is working through Seam ContextFilter). So we don’t change Seam request processing completely, but create the way to make exceptions in request processing, so we can create requests which will not cause our conversations to be timed-out.

   public void run() throws ServletException, IOException
   {
      log.debug("beginning request");

      // Force creation of the session
      if (request.getSession(false) == null)
      {
         request.getSession(true);
      }

      // Begin request and Seam life cycle only if it is not nested
      // ContextualHttpServletRequest
      if (getCounterValue() == 0)
      {
         ServletLifecycle.beginRequest(request);
         ServletContexts.instance().setRequest(request);
         restoreConversationId();
         Manager.instance().restoreConversation();
         ServletLifecycle.resumeConversation(request);
         handleConversationPropagation();
      }

      try
      {
         incrementCounterValue();

         process();

         decrementCounterValue();

         // End request only if it is not nested ContextualHttpServletRequest
         if (getCounterValue() == 0)
         {
//            Manager.instance().endRequest( new ServletRequestSessionMap(request)  );
            ServletLifecycle.endRequest(request);
         }
      }
      catch (IOException ioe)
      {
         removeCounter();
         Lifecycle.endRequest();
         log.debug("ended request due to exception");
         throw ioe;
      }
      catch (ServletException se)
      {
         removeCounter();
         Lifecycle.endRequest();
         log.debug("ended request due to exception");
         throw se;
      }
      catch (Exception e)
      {
         removeCounter();
         Lifecycle.endRequest();
         log.debug("ended request due to exception");
         throw new ServletException(e);
      }
      finally
      {
         log.debug("ended request");
      }
   }

in the web.xml we declare the filter and servlets which will use it. We map this filter to the servlets which make periodic background calls to the server

    <filter>
        <filter-name>No Conversation Timeout Filter</filter-name>
        <filter-class>ContextFilterWithoutTimeout</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>No Conversation Timeout Filter</filter-name>
        <servlet-name>LongOperationsServlet</servlet-name>
    </filter-mapping>
    <filter-mapping>
        <filter-name>No Conversation Timeout Filter</filter-name>
        <servlet-name>PollServlet</servlet-name>
    </filter-mapping>

As I said before – it doesn’t completely change the Seam request processing, it just let us to avoid conversation timeout for our primary page. In case user will open two pages and leave them for certain time (larger than configured conversation timeout) – only the first page he will interact with will continue conversation, because on the first interaction the other conversation 9form other page) will be timed out. But that is expected behavior of Seam conversations and we are not going to change it. What we solve here – is that our primary conversation will not be destroyed because of our background (secondary) calls and that those secondary calls will have an access to all Seam components.

Tagged with: , , , , , , , , ,
Posted in Software Development, Tips and Tricks

Conditional re-rendering in JSF (Richfaces)


It happens that you want something to be re-rendered only if ajax-request is executed without errors. Or in other words – you want to be lazy if it possible and not perform “reRender” if you could. Just like that funny guy – he have to be lazy to be strong 🙂
For example you have a dialog which call some ajax-action and you want to re-render it only if ajaxrequest is executed without errors
if yo’ll put a plain it will always reRender the “list” – even if ajax request has errors.


<a4j:commandLink action="#{actionBean.action}" reRender="list" value="Run"
onComplete="if (!hasAjaxErrors()){closeModalPanel();}"/>

the workaround could be moving the reRendering to a separate a4j:jsFunction call and call it only when you want it


<a4j:commandLink action="#{actionBean.action}" value="Run
onComplete="if (!hasAjaxErrors()){closeModalPanel();onCompleteFunction()}"/>

<a4j:jsFunction name="onCompleteFunction" reRender="list" ajaxSingle="true"/>

pretty easy and your “list” will be reRendered only after success call to the “#{actionBean.action}”

XHTML code to inject the error-severity in the input field “requestSeverity”

    <a4j:outputPanel ajaxRendered="true" id="severityPanel">
        <h:form prependId="false" style="display:none" >
            <h:inputHidden id="requestSeverity"
value="#{facesContext.maximumSeverity.ordinal}"/>
        </h:form>
    </a4j:outputPanel>

Javascript function to check presence of errors (error-messages-severity)

function hasAjaxErrors() {
    var errorSeverityElement = document.getElementById("requestSeverity");
    if (errorSeverityElement){
        return errorSeverityElement.value >= 2;
    }
    return false;
}
Tagged with: , , , , ,
Posted in Software Development, Tips and Tricks

Useful Eclipse navigation shortcuts for java developer

I find that this article (10 Eclipse Navigation Shortcuts…) is great and will save you a lot of time in development/coding if you are programming in Eclipse. I personally prefer Intellij Idea for java development, but in case of Android “Eclipse + ADT plugin” doesn’t leave much chances to alternative IDE’s.
Great shortcuts, I use part of them before and really miss “CTRL-E” Go to other open editors

Go to other open editor

and “CTRL-O” Go directly to a member (method, variable)

Tagged with: , , ,
Posted in Android, Tips and Tricks

Richfaces a4j:poll and a4j:push Can Do More Together

Task: Update the content of the page if the content is changed on server-side, in other words – show the most-fleshiest content to the user.

The most simple solution that comes to mind is to use <a4j:poll/> component which will periodically call some action which will load fresh content and re-render the content on the page. But that not very optimal since you will create the content on server-side and send it back to the client each time you execute the polling request.

a4j:push component looks like the one who was created to avoid that every-time re-rendering. Here is what demo-site says about it:

The main difference between a4j:push and a4j:poll components is that a4j:push makes request to minimal code only (not to JSF tree) in order to check the presence of messages in the queue. If the message exists the complete request will be performed. The component doesn’t poll registered beans but registers EventListener which receives messages about events.

Looks very promising, but in reality it’s a kind of tricky to integrate it with your real application because some code on the server side should execute something like that:

synchronized (listener) {
listener.onEvent(new EventObject(this));
}

But, to do so we should have something in background which will periodically check for updates and generate the events and send them to our listener. Starting a Thread is not good option since we have to worry about the way to stop it, as well who start Thread’s in web-apps ? @Asynchronous task is better one option, but still has the same issues – we have to worry about it lifecycle and stop updates at some point (user may leave the page or close his browser) so we actually has no good way to manage the lifecycle of launched background tasks.
At first I try to use a4j:push with action=”#{myActionBean.checkForUpdates}” but action is not called by a4j:push, it just checks if he has new events and only if it has such – execute action and do reRendering (all that JSF lifecycle) 

But it looks like combination of a4j:poll and a4j:push could work here in that way.

  • a4j:poll execute an action which check for updates in the data and fire an Event if they are exists
  • a4j:push periodically check for new events and re-render content on new event

So, a4:poll play role of assistant, actually it’s like the managed background task on the serverside which periodically poll for the data, but it’s live on the client-side, so in case user will close his browser – server will not execute the requests to datsource anymore.

I call it a “conditional re-rendering”. Here is the JSF code I use to make it working.

<a4j:form id="pollForm" eventsQueue="queue">
    <a4j:region id="pollRegion" selfRendered="true" renderRegionOnly="true">
        <a4j:poll action="#{myActionBean.checkForNewData}"
            id="datasetChangedChecker" interval="#{myActionBean.pollInterval}"
            ajaxSingle="true" limitToList="true" immediate="true" bypassUpdates="true">
        </a4j:poll>
    </a4j:region>
<!-- the function below execute an ajax-call to server which enable the push and re-render <a4j:push /> to start it -->
<a4j:jsFunction name="startPushUpdates"
                action="#{myActionBean.startPushUpdates}"
                reRender="dataSetReRendererPush" ajaxSingle="true"/>
</a4j:form>

<a4j:form id="pushForm" eventsQueue="queue">
    <a4j:push id="dataSetReRendererPush" ajaxSingle="true"
              eventProducer="#{myActionBean.addUpdatesListener}"
              interval="#{myActionBean.pollInterval}"
              reRender="contentPanel,datasetChangedChecker,dataSetReRendererPush"
              enabled="#{myActionBean.pushUpdatesStarted}"
     />
</a4j:form>

<a4j:outputPanel id="contentPanel">
   <!-- Updated content goes here -->
</a4j:outputPanel>

The only issue here is that we have to ensure that a4j:push is executed AFTER a4j:poll so action called in a4j:poll will generate the event before we will execute the a4j:push. Unfortunately we don’t have the way to manage it in JSF with attributes, but that could be done with help of postponed launching of a4j:push (with some reasonable gap which should be bigger than time required to execute check for data-updates)
The postponed a4j:push execution is achieved with enabling it with ‘enabled=”#{myActionBean.pushUpdatesStarted}”‘ attribute and calling the javascript with timeout

jQuery(document).ready(function() {
    window.setTimeout(startPushUpdates, 5000);
});

so, having all that JSF code and MyActionBean.java we have quite optimal solution
I didn’t include java-code here but I believe if you read this line than you most probably got the idea and capable to implement it on your own 🙂

Future notes: it looks that IceFaces propose their own vision of ajax-push and it’s not based on periodical polling of server from server-side.
IceFaces push model
As well they have Direct-To-Dom rendering which looks like much more optimal way of re-Rendering. Haven’t tried it yet, but for me it looks ajax-push at IceFaces and re-rendering is a more optimal solution.
It would be nice to hear from the ones who try both RichFaces and IceFaces ajax push approaches.
BTW, just find that RichFaces team prepare some updates to a4j:push in RF-4.0

With this release we have added a few new components, redesigned a4j:push to use advanced Comet implementation and JMS servers

Tagged with: , , , , , ,
Posted in Software Development, Tips and Tricks

Export to Excel with jXLS can be faster

I got a question about the jXLS performance, in short it was like “jXLS is a kind of slow for my big reports”.
I mentioned that in my previous post (Creating Excel reports from java is easy)

It’s true, especially about latest jXLS, after I updated my jxls-0.9.8 to 1.0-RC1 (see downloads) I noticed that report generation become MUCH SLOWER. I believe the difference is in the expression library version JEXL. In the 1.0-RC1 they start using JEXL-2.0.1 version and before they use JEXL-1.1
Anyway, it looks downgrading it back to the jXLS 0.9.8 solves my problems, the performance is not blazing fast but much better than in jXLS 1.0. I bet jXLS 0.9.9 work faster than 1.0

Tagged with: , , , ,
Posted in Software Development, Tips and Tricks

Howto disable form submit on Enter and fix for RichFaces rich:inputNumberSpinner

It’s quite generic problem – to disable automatic form submit on ENTER, to avoid occasional submits which could lead either to page refresh or even to redirecting to another page.
The general idea is to define onkeypressed event handler for text input fields
Here is the article which describe the general approach to do it in HTML.

we can assign onkeypressed event handler to all fields just with few lines (with help of JQuery of course)

function noEnter() {
    return !(window.event && window.event.keyCode == ENTER_KEY_CODE);
}

jQuery(document).ready(function(){
      jQuery(:input:text).keypress(function(){
           return noEnter();
      });
});

That works fine for a lot of components, but not for rich:inputNumberSpinner.  “onkeypressed” handler was assigned and was called, but … it still not work, after a plenty time in debug I finally ensured that it not working and start investigating the richfaces sources for that component and found that it has a javascript command that DIRECTLY perform the form submit. And there is no way to prevent this behavior using tags or javascript handlers.
BTW – I really like new google-chrome developer tools, pretty good and *faster* alternative to FireBug in FF)

After some googling I  found that there is an RF issue exists (not resolved yet) and there is no way to prevent form submission according to the richfaces-issue and actually in the related-post this issue is described in details, but it looks that solution could be only fixing the RichFaces library itself.
So, let’s do it!  We will need to build it form sources, since direct update of the script in the jar-file is not working – richfaces have minified scripts and they are pretty hard to read/modify 🙂

You can download patched richfaces-ui.jar from here.

  1. Download RichFaces sources (I prefer to use stable builds)
  2. Extract them and navigate to the file in which form-submission is done “ui/inputnumber-spinner/src/main/resources/org/richfaces/renderkit/html/script/SpinnerScript.js”
  3. comment out that crazy row
            if (e.keyCode == 13){
                if (this.spinner.required || "" != this.edit.value)
                    this.edit.value = this.getValidValue(this.edit.value);
                if (this.edit.form) {
    //                this.edit.form.submit();
                }
            }
    }
    
  4. Lets build the Richfaces from sources. The first problem you can met is the memory. We will need a bunch of memory, so ensure that you have 64-bit java (since you will need a lot of memory – about 1500MB – I was not able to allocate this amount on 32-bit java in Windows-XP)
    so, instead of redefining env variables I just copied mvn.bat to mvn64.bat and added the following lines

    set JAVA_HOME=E:/Java/jdk/jdk.1.6_64
    set MAVEN_OPTS=-Xms512m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m
    
  5. no lets rebuild richfaces-ui to do it, let’s grab few command-lines from developmentBuild.sh
    cd %PROJECT_DIR%/ui
    mvn64  clean install -Dmaven.test.skip=true
    cd %PROJECT_DIR%/ui/assembly
    mvn64  clean install -Dmaven.test.skip=true
    
  6. Let’s take a cup of tea since it will take a while…
  7. After build is done you will find the updated richfaces-ui.jar in the local maven repository.
    ${repository-home}/org/richfaces/ui/richfaces-ui/3.3.3.Final/richfaces-ui-3.3.3.Final.jar
Tagged with: , , , , , ,
Posted in Software Development, Tips and Tricks