Monday, September 10, 2012


jquery.table.filler

jquery.table.filler

This project aims to explain how to create a jQuery plug-in (minimum jQuery version is 1.4.2).

By the way, I'm going to use this example to build a table filler which loads JSON data from a remote and local resource and puts the data into the table as they are retrieved.

Soon I'll start a new jQuery plug-in project based upon this one to handle pagination!


What you need is:

  • jQuery 1.4.2+
  • a browser: Firefox 3+ or Chrome 7+ or Safari (I do not have a Mac so...) - never tested on IE and I will not!

Github

https://github.com/foogaro/jquery.table.filler


What is it about?

Actually I'm always facing with jQuery plug-in to fill data into table a handle pagination. I tried many of them, but none fits my needs. So I decided to write my own, starting at the very beginning. First a jQuery plug-in which loads data and puts them into the table!

To look at the complete source with comments, have a look at my github project!


The code (partial)

I'll show you step by step how I did it.


Startup for the jQuery plug-in mechanism

(function($) {

    var settings = {
        data: null,
        dataUrl: '',
        loader: false,
        tableInstance: null,
        headersSize: 0,
        columnsSize: 0,
        emptyDataMessage: 'No data found'
    };

    var methods = {};

    $.fn.tableFiller = function( method ) {
        if ( methods[method] ) {
            return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.tableFiller' );
        }
    };

})(jQuery);


As you can see the code is pretty much self explained.
I have a variable where I put all my settings, an object called methods where I'm going to declare all my methods, and the final part is where I extend jQuery to enable my plug-in.



The methods

        init : function(options) {
            if (options) {
                $.extend(settings, options);
            }

            settings.tableInstance = this;
            $(settings.tableInstance).show();

            if (settings.data != null) {
                methods.analyzeData(settings.data.data);
            } else {
                methods.loadData(settings.dataUrl);
            }
        },
        analyzeData: function (data) {
            if (data && data.headers) {
                methods.buildHeader(data.headers);
            }
            settings.headersSize = $('thead tr th',settings.tableInstance).size();

            if (data && data.rows) {
                methods.fillTable(data.rows);
            } else {
                methods.handleNoDataFound(null);
            }
        },
        loadData: function(uri) {
            $.ajax({
                url: uri,
                success: function (response, textStatus, xhr) {
                    if (response && response.data) {
                        methods.analyzeData(response.data)
                    }
                },
                error: function (xhr, textStatus, errorThrown) {
                    methods.handleLoadDataError(textStatus);
                }
            });
        },
        fillTable: function (rows) {
            $('tbody', settings.tableInstance).remove();
            $(settings.tableInstance).append('');

            if (rows.length > 0) {
                for (var rowIndex in rows) {
                    $('tbody', settings.tableInstance).append('');
                    var row = rows[rowIndex];
                    for (var columnsIndex in row) {
                        var columns = row[columnsIndex];
                        for (var ind in columns) {
                            $('tbody tr:last', settings.tableInstance).append('' + columns[ind] + '');
                        }
                    }
                }
            } else {
                methods.handleNoDataFound();
            }
        },
        buildHeader: function(headers) {
            $('thead', settings.tableInstance).remove();
            $(settings.tableInstance).prepend('');
            $("thead", settings.tableInstance).append('');
            for (var headerIndex in headers) {
                $('thead tr:first', settings.tableInstance).append('' + headers[headerIndex] + '');
            }
        },
        handleNoDataFound: function() {
            $('tbody', settings.tableInstance).remove();
            $(settings.tableInstance).append('');
            $('tbody', settings.tableInstance).append('' + settings.emptyDataMessage + '');
        },
        handleLoadDataError: function(msg) {
            alert(msg);
            $("#tableFillerErrorMessage").empty();
            $("#tableFillerErrorMessage").remove();
            $(settings.tableInstance).hide();
            $("body").append('
Error while loading data - ' + textStatus + '
'); }

Think about the init as a costructor, where I handle options.
Based on what is in the options I load data from a remote source (dataUrl) or just fill in the table with the data (data).

Those methods are contained inside the methods variable.


An HTML page to test it


    

        
        -{foogaro.com}- jQuery plug-in | Table-filler
        
        

        
    
    

        
        

        



Why am I sharing this?

I'm sure I'll need that sooner or later!


Hope, it helps!

Ciao, Foogaro

Thursday, September 6, 2012


New github project - resteasy-json-xml

resteasy-json-xml

This project aims to explain how to use RESTeasy 1.2.1.GA with JBoss EAP 5.1.2 when you deal with @Form and @FormParam.

Also you will find how to use URL-based content negotation to retrieve data in the format you like.

Soon I'll code the same project using RESTeasy 2.


What you need is:

  • Maven 2+
  • JDK 5+
  • JBoss EAP 5.1.2 or JBoss AS 6
  • The IDE you like, preferably a good one. Any IDEA out there? ;-)

Github

https://github.com/foogaro/resteasy-json-xml


What is it about?

In few words, about error you hit during test, which sometimes are not easy to fix - not because of you, but 'cause of the not clear stack trace.


Here they are

I'll show you just the stack trace, solution are reported and commented into the code.


org.jboss.resteasy.plugins.providers.jaxb.JAXBMarshalException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions

16:17:22,593 ERROR [org.jboss.resteasy.core.SynchronousDispatcher.handleFailure] Failed executing GET /library/books
org.jboss.resteasy.plugins.providers.jaxb.JAXBMarshalException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Invalid @XmlElementRef : Type "class com.foogaro.resteasy.model.DataWrapper" or any of its subclasses are not known to this context.
    this problem is related to the following location:
        at public com.foogaro.resteasy.model.DataWrapper com.foogaro.resteasy.model.Result.getData()
        at com.foogaro.resteasy.model.Result


org.jboss.resteasy.spi.WriterException: java.lang.IllegalStateException: Invalid JSON namespace: http://www.w3.org/2001/XMLSchema-instance

09:14:48,143 ERROR [org.jboss.resteasy.core.SynchronousDispatcher.handleFailure] Failed executing POST /library/authors.json
org.jboss.resteasy.spi.WriterException: java.lang.IllegalStateException: Invalid JSON namespace: http://www.w3.org/2001/XMLSchema-instance
 at org.jboss.resteasy.core.ServerResponse.writeTo(ServerResponse.java:197)
 at org.jboss.resteasy.core.SynchronousDispatcher.writeJaxrsResponse(SynchronousDispatcher.java:485)
 at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:422)
 at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:111)
 at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:217)
 at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:159)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:183)
 at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:95)
 at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
 at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.internalProcess(ActiveRequestResponseCacheValve.java:74)
 at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:47)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:599)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:451)
 at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.IllegalStateException: Invalid JSON namespace: http://www.w3.org/2001/XMLSchema-instance
 at org.codehaus.jettison.mapped.MappedNamespaceConvention.getJSONNamespace(MappedNamespaceConvention.java:182)
 at org.codehaus.jettison.mapped.MappedNamespaceConvention.createAttributeKey(MappedNamespaceConvention.java:170)
 at org.codehaus.jettison.mapped.MappedXMLStreamWriter.writeAttribute(MappedXMLStreamWriter.java:90)
 at com.sun.xml.bind.v2.runtime.output.XMLStreamWriterOutput.attribute(XMLStreamWriterOutput.java:133)
 at com.sun.xml.bind.v2.runtime.XMLSerializer.attribute(XMLSerializer.java:435)
 at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
 at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:152)
 at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:332)
 at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:593)
 at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:320)
 at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494)
 at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:315)
 at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:172)
 at org.jboss.resteasy.plugins.providers.jaxb.json.JettisonMappedMarshaller.marshal(JettisonMappedMarshaller.java:71)
 at org.jboss.resteasy.plugins.providers.jaxb.BaseMarshaller.marshal(BaseMarshaller.java:24)
 at org.jboss.resteasy.plugins.providers.jaxb.AbstractJAXBProvider.writeTo(AbstractJAXBProvider.java:105)
 at org.jboss.resteasy.core.interception.MessageBodyWriterContextImpl.proceed(MessageBodyWriterContextImpl.java:117)
 at org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor.write(GZIPEncodingInterceptor.java:48)
 at org.jboss.resteasy.core.interception.MessageBodyWriterContextImpl.proceed(MessageBodyWriterContextImpl.java:123)
 at org.jboss.resteasy.core.ServerResponse.writeTo(ServerResponse.java:186)
 ... 28 more



Why am I sharing this?

I'm sure I'll need that sooner or later!


Hope, it helps!

Ciao, Foogaro