NoVDL: Write your JSF views in pure Java

By , 17 March 2016

NoVDL: Write your JSF views in pure Java

Ever had to stare down a stack trace like this?

ApplicationImpl.newThing:1728
ApplicationImpl.createComponentApplyAnnotations:1894
ApplicationImpl.createComponent:1164
ComponentTagHandlerDelegateImpl.createComponent:524
ComponentTagHandlerDelegateImpl.apply:168
DelegatingMetaTagHandler.apply:120
CompositeFaceletHandler.apply:98
DelegatingMetaTagHandler.applyNextHandler:137
BehaviorsAddingComponentHandlerWrapper.applyNextHandler:53
ComponentTagHandlerDelegateImpl.apply:195
DelegatingMetaTagHandler.apply:120
CompositeFaceletHandler.apply:98
DelegatingMetaTagHandler.applyNextHandler:137
BehaviorsAddingComponentHandlerWrapper.applyNextHandler:53
ComponentTagHandlerDelegateImpl.apply:195
DelegatingMetaTagHandler.apply:120
CompositeFaceletHandler.apply:98
DelegatingMetaTagHandler.applyNextHandler:137
BehaviorsAddingComponentHandlerWrapper.applyNextHandler:53
ComponentTagHandlerDelegateImpl.apply:195
DelegatingMetaTagHandler.apply:120
IfHandler.apply:96
CompositionHandler.apply:166
NamespaceHandler.apply:93
EncodingHandler.apply:86
DefaultFacelet.include:308
DefaultFacelet.include:367
DefaultFaceletContext.includeFacelet:326
UserTagHandler.apply:142
CompositeFaceletHandler.apply:98
InsertHandler.apply:117
CompositeFaceletHandler.apply:98
CompositionHandler.apply:166
NamespaceHandler.apply:93
EncodingHandler.apply:86
DefaultFacelet.include:308
DefaultFacelet.include:367
DefaultFacelet.include:346
DefaultFaceletContext.includeFacelet:199
IncludeHandler.apply:120
IfHandler.apply:96
CompositeFaceletHandler.apply:98
DefineHandler.applyDefinition:107
DecorateHandler.apply:161
DefaultFaceletContext$TemplateManager.apply:395
DefaultFaceletContext.includeDefinition:366
InsertHandler.apply:112
CompositeFaceletHandler.apply:98
DelegatingMetaTagHandler.applyNextHandler:137
BehaviorsAddingComponentHandlerWrapper.applyNextHandler:53
ComponentTagHandlerDelegateImpl.apply:195
DelegatingMetaTagHandler.apply:120
CompositeFaceletHandler.apply:98
ViewHandler.apply:182
NamespaceHandler.apply:93
CompositeFaceletHandler.apply:98
EncodingHandler.apply:86
DefaultFacelet.include:308
DefaultFacelet.include:367
DefaultFacelet.include:346
DefaultFaceletContext.includeFacelet:199
DecorateHandler.apply:145
NamespaceHandler.apply:93
EncodingHandler.apply:86
DefaultFacelet.include:308
DefaultFacelet.include:367
DefaultFacelet.include:346
DefaultFaceletContext.includeFacelet:199
DecorateHandler.apply:145
NamespaceHandler.apply:93
EncodingHandler.apply:86
DefaultFacelet.include:308
DefaultFacelet.include:367
DefaultFacelet.include:346
DefaultFaceletContext.includeFacelet:199
DecorateHandler.apply:145
NamespaceHandler.apply:93
EncodingHandler.apply:86
DefaultFacelet.apply:152

Sorry to do that to you. I know you've seen enough of that already. But don't worry, I'm about to make it up to you by introduction NoVDL.

NoVDL is a View Description Language that makes your JSF views more robust by implementing them in Java. By using Java to write your views you automatically gain many features.

  • type safety
  • compile-time code verification
  • stack traces that actually make sense
  • ide autocomplete support
  • ide refactoring support
  • java static methods for composite components
  • java function composition for decorating views
  • java inheritance for decorating views
  • java object references to access components
  • java method references to invoke action listeners
  • java namespacing for component libraries
  • high performance
  • less reliance on flaky EL expressions
  • less reliance on managed beans
  • no XML configuration, taglibs, or magic annotations
  • one language to learn instead of three (Java + XML + EL)

Example View

public class OrderForm extends BasePage implements Activity {

    @Override
    public void buildView(FacesContext faces, UIViewRoot root) {
        List<Product> products = ProductDAO.getAllProducts();
        UIPanelGroup main = 
          h_panelGroup().children(
            f_verbatim("<h1>Order Form</h1>"),
            h_form().id("order").children(
              h_dataTable().id("products").value(products).var("product").width("100%").children(
                h_column().header(f_verbatim("Description")).children(
                  h_outputLink().id("link").valuex("${product.page.linkURL}").children(
                    h_outputText().valuex("${product.description}")
                  )
                ),
                h_column()
                    .header(f_verbatim("Quantity"))
                    .children(h_inputText().id("quantity").converter(new IntegerConverter())
                    .footer(h_commandButton().id("submit").value("Create Order")
                                    .actionListener(createOrder()))
                )
              )
            )
          );


        /*
         * If your master template is implemented in java you'll create a 
         * separate function to build it, e.g.
         *
         * build_master_view(faces, root, main);
         *
         * NoVDL also includes a function to execute a facelet which can 
         * then include the partial view you created here using a 
         * binding=".." attribute.
         */
        build_from_facelet(faces, root, getMasterTemplate());
    }
}

Mapping Routes

The current implementation maps the view id to its Java implementation by converting the url path to a class name. E.g.

http://localhost/com/example/Demo.xhtml

is routed to the class

com.example.Demo

If you need different functionality, you could rewrite get_view_class_name() and recompile NoVDL. If there is enough demand, I'll make this function configurable.

Value Expressions

NoVDL allows value expressions to be set by using the setter method which ends in x. e.g.

h_outputText().value("Hello World"); // or
h_outputText().valuex("${bean.greeting}");

This was chosen partly because the NoVDL components are automatically generated from the JSF API, and partly because EL is discouraged in NoVDL. Ideally, we'd like to be able to implement ValueExpressions using lambda functions.

Composite Components with a Static Factory

It is very easy to make composite components using a static factory method.

public static UIPanel create_data_grid(Data current) {
    HPanelGrid grid = h_panelGrid().id("ox_related").columns(4);
    for (Match match : data.getMatches()) {
        HPanelGroup panel = h_panelGroup().id("ox_related_" + match.getId());
        if (match.getThumbnail() != null) {
            panel.children(
                h_outputLink().value(match.getLinkURL()).children(
                    h_graphicImage().value(match.getThumbnail())
                )
            );
        }
        panel.children(
            f_verbatim("<p>"),
            h_outputLink().value(match.getLinkURL()).children(
                h_outputText().value(match.getTitle())
            ),
            f_verbatim("</p>")
        );
        grid.getChildren().add(panel);
    }
    return grid;
}

This is a good example of why XML is a questionable choice for user interfaces. Is it declarative code or is it procedural? Actually, it's a mixture, and there is not much advantage to declarative languages when you start to mix in procedural (or functional) code.

Decorating Views using Functions

Same idea as above. e.g.

public static void decorate_view(FacesContext faces, UIViewRoot root,
        UIHead head, UIComponent content) {
    root.getChildren().add(head);
    root.getChildren().add(
        h_body().children(
            content
        );
}

Decorating Views using Inheritance

Function composition is preferred over inheritance. If you like inheritance, all you need to do is make an abstract superclass that defines the sections of your view. e.g.

public abstract class MasterView implements Activity {

    @Override
    public void buildView(FacesContext faces, UIViewRoot root) {
        root.getChildren().add(build_head(faces));
        root.getChildren().add(
            h_body().children(
                build_content(faces)
            );
    }

    public abstract UIHead build_head(FacesContext faces);
    public abstract UIComponent build_content(FacesContext faces);
}

Mixing Facelets and Java Views

Use the function

build_from_facelet(faces, root, template);

to execute a Facelet from your buildView function. Inside that template, you'll have to reference the components you built using NoVDL. e.g.

<h2>Current Data</h2>
<div class="web_noprint">

  <!-- datagrid is prebuilt with NoVDL -->
  <h:panelGroup binding="${someBean.datagrid}"/>
</div>

Editing Views on the Fly

Facelets lets you edit views on the fly without recompiling or restarting the application. You should be able to use HotSwapAgent or JRebel to achieve the same thing with NoVDL.

Installation

NoVDL is automatically detected when you add the following dependency. View IDs that cannot be mapped to Java implementations will fall back on the default view decoration language (normally Facelets).

<dependency>
  <groupId>au.com.ninthavenue.jamaica.faces</groupId>
  <artifactId>novdl</artifactId>
  <packaging>jar</packaging>
  <version>1.0</version>
</dependency>

Note: NoVDL requires Java 8.

Get the Source

https://github.com/rogerkeays/novdl

Spend some time experimenting with NoVDL and let me know how it works for you.

No comments yet, be the first to comment!

How to Test if a File is PDF (Java)

By , 26 February 2016

How to Test if a File is PDF (Java)

Here is a simple java function to check if some data represents a PDF file. It is adapted from a C# function posted on Stack Overflow by NinjaCross.

    /**
     * Test if the data in the given byte array represents a PDF file.
     */
    public static boolean is_pdf(byte[] data) {
        if (data != null && data.length > 4 &&
                data[0] == 0x25 && // %
                data[1] == 0x50 && // P
                data[2] == 0x44 && // D
                data[3] == 0x46 && // F
                data[4] == 0x2D) { // -

            // version 1.3 file terminator
            if (data[5] == 0x31 && data[6] == 0x2E && data[7] == 0x33 &&
                    data[data.length - 7] == 0x25 && // %
                    data[data.length - 6] == 0x25 && // %
                    data[data.length - 5] == 0x45 && // E
                    data[data.length - 4] == 0x4F && // O
                    data[data.length - 3] == 0x46 && // F
                    data[data.length - 2] == 0x20 && // SPACE
                    data[data.length - 1] == 0x0A) { // EOL
                return true;
            }

            // version 1.3 file terminator
            if (data[5] == 0x31 && data[6] == 0x2E && data[7] == 0x34 &&
                    data[data.length - 6] == 0x25 && // %
                    data[data.length - 5] == 0x25 && // %
                    data[data.length - 4] == 0x45 && // E
                    data[data.length - 3] == 0x4F && // O
                    data[data.length - 2] == 0x46 && // F
                    data[data.length - 1] == 0x0A) { // EOL
                return true;
            }
        }
        return false;
    }

The function takes a byte[] to make it possible to test data in streams and files. To read a file into a byte array you can use java.nio.Files.readAllBytes, e.g:

    assertTrue(is_pdf(Files.readAllBytes(Paths.get("output.pdf"));

You'll have to handle the IOExceptions from those methods too. To test streamed output, just render to a ByteArrayOutputStream and call the getBytes() method after the output has rendered.

The unit tests for this function are below. Please feel free to contribute test cases, especially ones that fail.

    @Test
    public void test_valid_pdf_1_3_data_is_pdf() {
        assertTrue(is_pdf("%PDF-1.3 CONTENT %%EOF \n".getBytes()));
    }

    @Test
    public void test_valid_pdf_1_4_data_is_pdf() {
        assertTrue(is_pdf("%PDF-1.4 CONTENT %%EOF\n".getBytes()));
    }

    @Test
    public void test_invalid_data_is_not_pdf() {
        assertFalse(is_pdf("Hello World".getBytes()));
    }

No comments yet, be the first to comment!

Access Java Static Methods and Constants from EL

By , 24 September 2015

Access Java Static Methods and Constants from EL

Java EL 3.0 provides a way to access static variables and static methods from JSF or JSP, but it's a bit nasty, requiring you to import the packages into your EL Context. I'm lazy and have been using this hack since 2012, so I'm just going to keep doing it for EL 3.0. The hack I'm using makes static methods and constants available via normal managed beans. Note, I'm using Lombok annotations to generate the getters and setters automatically.

@ManagedBean
@ApplicationScoped
@Getter @Setter 
public class App {
    
    /* global compile-time constants */
    public static final String ROOT_DIR = "/var/local";
    public static final String UPLOADS_DIR = "/var/local/uploads";
    public static final String IMAGE_DIR = "/var/local/images";
    public static final String MANAGER_ROLE = "manager";

    /* EL accessors for static constants */
    String root_dir = ROOT_DIR;
    String uploads_dir = UPLOADS_DIR;
    String image_dir = IMAGE_DIR;
    String manager_role = MANAGER_ROLE;

    /* EL accessors for static methods */
    public long ctime() {
       return System.currentTimeMillis();
    }
}

Read more...

4 comments, post a comment!

Java With No Design Patterns

By , 13 September 2015

Java With No Design Patterns

What have I done?

I look down at the code I have just written. It's just one file with one static function and four unit tests. There are no factories, no singletons, no dependency injection, no local or remote interface, no containers, no special annotations, no xml configuration, no inheritence hierarchy, no fancy polymorphism, no abstraction, no black magic, no UML diagrams, no dependencies, no interfaces, no mocks and no side effects.

It's just code and tests.

    public class ProcessBeacon implements APILayer {

        public static boolean processBeacon(Long id, String email, String clientIP) {
           // code goes here
        }
        
        @Test
        public void processing_a_beacon_logs_an_action_in_the_database() {
          // test goes here
        }

        @Test
        public void processing_a_beacon_increments_the_open_count() {
          // test goes here
        }

        @Test
        public void processing_a_beacon_validates_the_recipients_email_address() {
          // test goes here
        }

        @Test
        public void processing_a_beacon_resets_the_recipients_bounce_count() {
          // test goes here
        }
    }

What has gotten into me? How dare I believe I can just write code like that? Without consideration for the greater scheme of object oriented nirvana. Without spending hours philosophising about which class in the universal hierarchy of things my function belongs to. Without considering how to perfectly name it, and how to access and instantiate it.

Shame on you. A beginner could have done what you just did.

Yes, a beginner could have done it and they would have been way ahead of us developers with over a decade of experience who have lost themselves in the storm of object-oriented design patterns.

I've always had this uncomfortable feeling that something was wrong with the way I code. A feeling that I don't know what I am creating. I visualise my applications as complex machine components interacting with each other in fascinating ways. I marvel at the intricacy of how they must be perfectly polished and oiled in order to mesh together. I picture the beauty of how the software agents seamlessly handle the docking of polymorphic components.

It's a fantastic image, but it fails to answer my nagging inquiry... what IS it?

Is it a machine? Is it a pattern? Is it a virtual life form? Or is it just a jumble of machine code?

In a way, my switch to a more basic, functional style of programming has answered my question. Object oriented systems do attempt to create a sort of virtual life form, but this is incongruent with the way computers actually work (and one of the reasons object-oriented design fails so badly at concurrency and multithreading).

Computers are Turing Machines which work by streaming long lists of operations which transform data held in the CPU registers. In other words, they simply perform *operations* on *data* and send the results to the user.

Now think about how functional programming works. With functional programming you basically chain operations which transform data provided as the input to the function. In other words, you simply perform *operations* on *data* and send the results to the user.

Are you starting to see a pattern?

Business applications are hugely dominated by operations on data, but unfortunately we've been so sucked into modeling we forget to write code that actually DOES STUFF. Instead we spend most of our time figuring out how to instantiate objects and arguing about it on the Internet.

So I've broken all the rules of object oriented design and am implementing all my operations as stateless static methods, one per file with accompanying test cases. I no longer waste my time modeling, I don't have to think about how to access the function (just CALL it!), I don't have to deliberate about where to put new functions and I can spend my somewhat limited brainpower on writing code that actually does something useful.

After all... models look great but they don't DO much.

2 comments, post a comment!

How To Catch A ClassNotFoundException

By , 13 April 2014

How To Catch A ClassNotFoundException

HTTP request from spammers trying to exploit our commenting system is causing a ClassNotFoundException deep in the JSF / Java code. Specifically, spammers are sending serialized objects in the javax.jsf.ViewState parameter for classes that no longer exist in our system. The resulting exception is this:

Read more...

No comments yet, be the first to comment!

Preserving JSF Request Parameters and REST URLs

By , 13 February 2013

Have you ever used a URL pattern something like this?

http://localhost/app/widgets/WidgetEditor.xhtml?id=300 

or perhaps this?

http://localhost/app/widgets/300/edit 

Well, as a JSF developer you've probably already realized a little problem. How do you remember the id from request to request? There are a few simple solutions.

Read more...

6 comments, post a comment!

JSF Error Pages That Actually Work

By , 27 October 2012

JSF Error Pages That Actually Work

Here is an annoying problem using JSF error pages for JSF requests. Everything looks just fine, HttpServletResponse.sendError() sends the error page, but JSF continues processing and starts throwing exceptions after the response is complete. This happens even if you call FacesContext.responseComplete(), and also when the error page is sent at different stages of the JSF lifecycle.

It seems like invoking the FacesServlet for sendError() breaks the state of the original FacesContext.

When sending an error during view build I get this exception:

Read more...

4 comments, post a comment!

Why Is Maven So Slow? [Solved]

By , 24 October 2012

Why Is Maven So Slow? [Solved]

I couldn't figure out why the heck my maven builds where taking so long. I thought Java was supposed to be fast these days and here I am waiting 30 seconds to run a unit test. So I did some digging and eventually found the problem.

On Linux, the default JVM is the Server JVM which does all sorts of useful optimisations for long running server process but is absolutely dog slow for building source code (this could also be a reason why the Linux community thinks Java sucks so much).

To find out what JVM you are running simply type:

$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)

If you see "Server VM" like the example above do me a favor and time your maven compile (mvn clean compile) then switch to the Client VM, time it again and post your results in the comments below.

Read more...

11 comments, post a comment!

How To Create Email From JSF Templates

By , 1 October 2012

Hi everybody. In this blog I'm going to share a little trick for creating emails using JSF Facelets templates. The concept is actually independent of JSF and could be used for any servlet-based technology.

Right, so the basic idea is to temporarily trick the ServletResponse object into writing all the content to an in-memory buffer, rather than streaming it to the client's browser. We then manually invoke the JSF render phase for the particular view using the special ServletResponse and voila!, the captured output can be put into an email.

Let's have a look at some of the code.

Read more...

15 comments, post a comment!

How To Change Maven's Default Resource Folder

By , 31 August 2012

Sometimes it's nice to have your projects resource files alongside the java source files they're related to. By default, Maven forces you to have a separate resource tree so, for example, whenever you need to a add a String for internationalization you have to go digging through your project's folders.

The good news is, you can change change maven's default resource folder this with this little bit of XML magic in Maven pom.xml.

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <excludes><exclude>**/*.java</exclude></excludes>
      </resource>
    </resources>
  </build>

Note this overrides the default location, so make sure src/main/resources is empty, or add to the pom.xml like this.

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <excludes><exclude>**/*.java</exclude></excludes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
      </resource>
    </resources>
  </build>

Don't forget to exclude the java files unless you want to ship your source code!

2 comments, post a comment!

< Prev1 2 3 4 5 Next >