Blog

Serving Static HTML With Nodjs And Grunt For Template-Development

A Simple Nodejs/Grunt-Development-Environment for static HTML-Templates

Nowadays, frontend-development is mostly done with Nodjs and Grunt.
On npm, there are plenty of useful plugin’s, that ease the development of HTML and CSS.
For example grunt-contrib-less to automate the compilation of LESS-sourcecode to CSS, or grunt-svgstore to pack several SVG-graphics in a single SVG-sprite.

Because of that, I decided to switch to Nodejs and Grunt to develop the HTML- and CSS-Markup for the templates, that I need for my Spring/Thymeleaf-Applications.
But as with everything new, I had some hard work, to plug together what I needed.
In this article I want to share, how I have set up a really minimalistic, but powerful development-environment for static HTML-templates, that suites all of my initial needs.

This might not be the best solutions, but it is a good starting point for beginners like me and it is here to be improved through your feedback!

You can browse the example-development-environment on juplo.de/gitweb, or clone it with:


git clone http://juplo.de/git/examples/template-development

After installing npm you have to fetch the dependencies with:


npm install

Than you can fire up a build with:


grunt

…or start a webserver for development with:


git run-server

Serving The HTML and CSS For Local Development

The hardest part while putting together the development-environment was my need to automatically build the static HTML and CSS after file-changes and serve them via a local webserver.
As I wrote in an earlier article, I often stumble over problems, that arise from the Same-origin policy when accessing the files locally through file:///-URI’s).

I was a bit surprised, that I could not find a simple explanation, how to set up a grunt-task to build the project automatically on file-changes and serve the generated HTML and CSS locally.
That is the main reason, why I am writing this explanation now, in order to fill that gap ;)

I realised that goal by implemnting a grunt-task, that spawn’s a process that uses the http-server to serve up the files and combine that task with a common watch-task:


grunt.registerTask('http-server', function() {

  grunt.util.spawn({
    cmd: 'node_modules/http-server/bin/http-server',
    args: [ 'dist' ],
    opts: { stdio: 'inherit' }
  });

});

grunt.registerTask('run-server', [ 'default', 'http-server', 'watch' ]);

The rest of the configuration is really pretty self-explaining.
I just put together the pieces I needed for my template development (copy some static HTML and generate CSS from the LESS-sources) and configured grunt-contrib-watch to rebuild the project automatically, if anything changes.

The result is put under dist/ and is ready to be included in my Spring/Thymeleaf-Application as it is.

Bypassing the Same-Origin-Policy For Local Files During Development

downloadable font: download failed …: status=2147500037

Are you ever stumbled accross weired errors with font-files, that could not be loaded, or SVG-graphics, that are not shown during local development on your machine using file:///-URI’s, though everything works as expected, if you push the content to a webserver and access it via HTTP?
Furthermore, the browsers behave very differently here.
Firefox, for example, just states, that the download of the font failed:


downloadable font: download failed (font-family: "XYZ" style:normal weight:normal stretch:normal src index:0): status=2147500037 source: file:///home/you/path/to/font/xyz.woff

Meanwhile, Chrome just happily uses the same font.
Considering the SVG-graphics, that are not shown, Firefox just does not show them, like it would not be able to at all.
Chrome logs an error:


Unsafe attempt to load URL file:///home/you/path/to/project/img/sprite.svg#logo from frame with URL file:///home/you/path/to/project/templates/layout.html. Domains, protocols and ports must match

…though, no protocol, domain or port is involved.

The Same-Origin Policy

The reason for this strange behavior is the Same-origin policy.
Chrome gives you a hint in this direction with the remark that something does not match.
I found the trail, that lead me to this explanation, while googling for the strange error message, that Firefox gives for the fonts, that can not be loaded.


The Same-origin policy forbids, that locally stored files can access any data, that is stored in a parent-directory.
They only have access to files, that reside in the same directory or in a directory beneath it.

You can read more about that rule on MDN.

I often violate that rule, when developing templates for dynamically rendered pages with Thymeleaf, or similar techniques.
That is, because I like to place the template-files on a subdirectory of the directory, that contains my webapp (src/main/webapp with Maven):


+ src/main/webapp/
  + css/
  + img/
  + fonts/
  + thymeleaf/templates/

I packed a simple example-project for developing static templates with LESS, nodejs and grunt, that shows the problem and the quick solution for Firefox presented later.
You can browse it on my juplo.de/gitweb, or clone it with:


git clone http://juplo.de/git/examples/template-development

Cross-Browser Solution

Unfortunately, there is no simple cross-browser solution, if you want to access your files through file:///-URI’s during development.
The only real solution is, to access your files through the HTTP-protocol, like in production.
If you do not want to do that, the only two cross-browser solutions are, to

  1. turn of the Same-origin policy for local files in all browsers, or
  2. rearrange your files in such a way, that they do not violate the Same-origin policy (as a rule, all resources linked in a HTML-file must reside in the same directory as the file, or beneath it).

The only real cross-browser solution is to circumvent the problem altogether and serve the content with a local webserver, so that you can access it through HTTP, like in production.
You can read how to extend the example-project mentioned above to achieve that goal in a follow up article.

Turn Of Security

Turning of the Same-origin policy is not recommended.
I would only do that, if you only use your browser, to access the HTML-files under development ‐ which I doubt, that it is the case.
Anyway, this is a good quick test to validate, that the Same-origin policy is the source of your problems ‐ if you quickly re-enable it after the validation.

Firefox:
Set security.fileuri.strict_origin_policy to false on the about:config-page.
Chrome:
Restart Chrome with --disable-web-security or --allow-file-access-from-files (for more, see this question on Stackoverflow).

Quick Fix For Firefox

If you develop with Firefox, there is a quick fix, to bypass the Same-origin policy for local files.

As the explanation on MDM stats, a file loaded in a frame shares the same origin as the file, that contains the frameset.
This can be used to bypass the policy, if you place a file with a frameset in the topmost directory of your development-folder and load the template under development through that file.

In my case, the frameset-file looks like this:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Frameset to Bypass Same-Origin-Policy
  </head>
  <frameset>
    <frame src="thymeleaf/templates/layout.html">
  </frameset>
</html>

Configure pac4j for a Social-Login along with a Spring-Security based Form-Login

The Problem – What will be explained

If you just want to enable your spring-based webapplication to let users log in with their social accounts, without changing anything else, pac4j should be your first choice.
But the provided example only shows, how to define all authentication mechanisms via pac4j.
If you already have set up your log-in via spring-security, you have to reconfigure it with the appropriate pac4j-mechanism.
That is a lot of unnecessary work, if you just want to supplement the already configured log in with the additionally possibility, to log in via a social provider.

In this short article, I will show you, how to set that up along with the normal form-based login of Spring-Security.
I will show this for a Login via Facabook along the Form-Login of Spring-Security.
The method should work as well for other social logins, that are supported by spring-security-pac4j, along other login-mechanisms provided by spring-security out-of-the-box.

In this article I will not explain, how to store the user-profile-data, that was retrieved during the social login.
Also, if you need more social interaction, than just a login and access to the default data in the user-profile you probably need spring-social. How to combine spring-social with spring-security for that purpose, is explained in this nice article about how to add social sign in to a spring-mvc weba-pplication.

Adding the Required Maven-Artifacts

In order to use spring-security-pac4j to login to facebook, you need the following maven-artifacts:


<dependency>
  <groupId>org.pac4j</groupId>
  <artifactId>spring-security-pac4j</artifactId>
  <version>1.2.5</version>
</dependency>
<dependency>
  <groupId>org.pac4j</groupId>
  <artifactId>pac4j-http</artifactId>
  <version>1.7.1</version>
</dependency>
<dependency>
  <groupId>org.pac4j</groupId>
  <artifactId>pac4j-oauth</artifactId>
  <version>1.7.1</version>
</dependency>

Configuration of Spring-Security (Without Social Login via pac4j)

This is a bare minimal configuration to get the form-login via Spring-Security working:


<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
    ">

  <security:http use-expressions="true">
    <security:intercept-url pattern="/**" access="permitAll"/>
    <security:intercept-url pattern="/home.html" access="isAuthenticated()"/>
    <security:form-login login-page="/login.html" authentication-failure-url="/login.html?failure"/>
    <security:logout/>
    <security:remember-me/>
  </security:http>

  <security:authentication-manager>
    <security:authentication-provider>
      <security:user-service>
  	<security:user name="user" password="user" authorities="ROLE_USER" />
      </security:user-service>
    </security:authentication-provider>
  </security:authentication-manager>

</beans>

The http defines, that the access to the url /home.html is restriced and must be authenticated via a form-login on url /login.html.
The authentication-manager defines an in-memory authentication-provider for testing purposes with just one user (username: user, password: user).
For more details, see the documentation of spring-security.

Enabling pac4j via spring-security-pac4j alongside

To enable pac4j alongside, you have to add/change the following:


<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
    ">

  <security:http use-expressions="true">
    <security:custom-filter position="OPENID_FILTER" ref="clientFilter"/>
    <security:intercept-url pattern="/**" access="permitAll()"/>
    <security:intercept-url pattern="/home.html" access="isAuthenticated()"/>
    <security:form-login login-page="/login.html" authentication-failure-url="/login.html?failure"/>
    <security:logout/>
  </security:http>

  <security:authentication-manager alias="authenticationManager">
    <security:authentication-provider>
      <security:user-service>
  	<security:user name="user" password="user" authorities="ROLE_USER" />
      </security:user-service>
    </security:authentication-provider>
    <security:authentication-provider ref="clientProvider"/>
  </security:authentication-manager>

  <!-- entry points -->
  <bean id="facebookEntryPoint" class="org.pac4j.springframework.security.web.ClientAuthenticationEntryPoint">
    <property name="client" ref="facebookClient"/>
  </bean>

  <!-- client definitions -->
  <bean id="facebookClient" class="org.pac4j.oauth.client.FacebookClient">
    <property name="key" value="145278422258960"/>
    <property name="secret" value="be21409ba8f39b5dae2a7de525484da8"/>
  </bean>
  <bean id="clients" class="org.pac4j.core.client.Clients">
    <property name="callbackUrl" value="http://localhost:8080/callback"/>
    <property name="clients">
      <list>
        <ref bean="facebookClient"/>
      </list>
    </property>
  </bean>

  <!-- common to all clients -->
  <bean id="clientFilter" class="org.pac4j.springframework.security.web.ClientAuthenticationFilter">
    <constructor-arg value="/callback"/>
    <property name="clients" ref="clients"/>
    <property name="sessionAuthenticationStrategy" ref="sas"/>
    <property name="authenticationManager" ref="authenticationManager"/>
  </bean>
  <bean id="clientProvider" class="org.pac4j.springframework.security.authentication.ClientAuthenticationProvider">
    <property name="clients" ref="clients"/>
  </bean>
  <bean id="httpSessionRequestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache"/>
  <bean id="sas" class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/>

</beans>

In short:

  1. You have to add an additional filter in http.
    I added this filter on position OPENID_FILTER, because pac4j introduces a unified way to handle OpenID and OAuth and so on.
    If you are using the OpenID-mechanism of spring-security, you have to use another position in the filter-chain (for example CAS_FILTER) or reconfigure OpenID to use the pac4j-mechanism, which should be fairly straight-forward.

    The new Filter has the ID clientFilter and needs a reference to the authenticationManager.
    Also, the callback-URL (here: /callback) must be mapped to your web-application!
  2. You have to add an additional authentication-provider to the authentication-manager, that references your newly defined pac4j-ClientProvider (clientProvider).
  3. You have to configure your entry-points as pac4j-clients.
    In the example above, only one pac4j-client, that authenticats the user via Facebook, is configured.
    You easily can add more clients: just copy the definitions from the spring-security-pac4j example.

That should be all, that is necessary, to enable a Facebook-Login in your Spring-Security web-application.

Do Not Forget To Use Your Own APP-ID!

The App-ID 145278422258960 and the accompanying secret be21409ba8f39b5dae2a7de525484da8 were taken from the spring-security-pac4j example for simplicity.
That works for a first test-run on localhost.
But you have to replace that with your own App-ID and -scecret, that you have to generate using your App Dashboard on Facebook!

More to come…

This short article does not show, how to save the retrieved user-profiles in your user-database, if you need that.
I hope, I will write a follow-up on that soon.
In short:
pac4j creates a Spring-Security UserDetails-Instance for every user, that was authenticated against it.
You can use this, to access the data in the retrieved user-profile (for example to write out the name of the user in a greeting or contact him via e-mail).

A Perfect Outline

Point Out Your Content: Utilize the HTML5 Outline-Algorithm

HTML5 introduces new semantic elements accompained by the definition of a new algorithm to calculate the document-outline from the mark up.
There are plenty of good explanations of these new possibilities, to point out your content in a more controlled way.
But the most of these explanations fall short, if it comes to how to put these new markup into use, so that it results in a sensible outline of the document, that was marked up.

In this article I will try to explain, how to use the new semantic markup, to produce an outline, that is usable as a real content table of the document – not just as an partially orderd overview of all headings.
I will do so, by showing simple examples, that will illuminate the principles behind the new markup.

All Messed Up!

Although, the ideas behind the new markup seems to be simple and clear, nearly nobody accomplishes to produce a sensible outline.
Even the big players, who guide us through the jungle of the new specifications and are giving great explanations about the subject, either fail on there sites (see by yourself with the help of the help of the h5o HTML5 Outline Bookmarklet), or produce the outline in the old way by the usage of h1h6 only, like the fabulous HTML5-bible Dive Into HTML5.

This is, because there is a lot to mix up in a wrong way, when trying to adopt the new features.
Here is, what I ended up with, on my first try to combine what I have learned about semantic elements and the document outline:

Example 01: Markup


<!DOCTYPE html>
<title>Example 01</title>
<header>
  <h2>Header</h2>
  <nav>Navigation</nav>
</header>
<main>
  <h1>Main</h1>
  <section>
    <h2>Section I</h2>
  </section>
  <section>
    <h2>Section II</h2>
    <section>
      <h3>Subsection a</h3>
    </section>
    <section>
      <h3>Subsection b</h3>
    </section>
  </section>
  <section>
    <h2>Section III</h2>
    <section>
      <h3>Subsection a</h3>
    </section>
  </section>
</main>
<aside>
  <h1>Aside</h1>
</aside>
<footer>
  <h2>Footer</h2>
</footer>

Example 01: Outline

  1. Header

    1. Untitled section
  2. Main

    1. Section I
    2. Section II

      1. Subsection a
      2. Subsection b
    3. Section III

      1. Subsection a
    4. Aside
    5. Footer

View example 01

That quiet was not the outline, that I had expected.
I planed, that Header, Main, Aside and Footer are ending up at the same level.
Instead of that, Aside and Footer had become sections of my Main-content.
And where the hell comes that Untitled section from?!?
My first thought on that was: No problem, I just forgot the header-tags.
But after adding them, the only thing that cleared out, was where the Untitled section was coming from:

Example 02: Markup


<!DOCTYPE html>
<title>Example 02</title>
<header>
  <h2>Header</h2>
  <nav>
    <header><h3>Navigation</h3></header>
  </nav>
</header>
<main>
  <header><h1>Main</h1></header>
  <section>
    <header><h2>Section I</h2></header>
  </section>
  <section>
    <header><h2>Section II</h2></header>
    <section>
      <header><h3>Subsection a</h3></header>
    </section>
    <section>
      <header><h3>Subsection b</h3></header>
    </section>
  </section>
  <section>
    <header><h2>Section III</h2></header>
    <section>
      <header><h3>Subsection a</h3></header>
    </section>
  </section>
</main>
<footer>
  <header><h2>Footer</h2></header>

Example 02: Outline

  1. Header

    1. Navigation
  2. Main

    1. Section I
    2. Section II

      1. Subsection a
      2. Subsection b
    3. Section III

      1. Subsection a
    4. Aside
    5. Footer

View example 02

So I thought: Maybe the main-tag was the wrong choice.
Perhaps it should be replaced by an article.
But after that change, the outline even got worse.
Now, Navigation, Main and Aside appeared on the same level, all as a subsection of Header.
At least, Footer suddenly was a sibling of Header as planed:

Example 03: Markup


<!DOCTYPE html>
<title>Example 03</title>
<header>
  <h2>Header</h2>
  <nav>
    <header><h3>Navigation</h333></header>
  </nav>
</header>
<article>
  <header><h1>Article (Main)</h1></header>
  <section>
    <header><h2>Section I</h2></header>
  </section>
  <section>
    <header><h2>Section II</h2></header>
    <section>
      <header><h3>Subsection a</h3></header>
    </section>
    <section>
      <header><h3>Subsection b</h3></header>
    </section>
  </section>
  <section>
    <header><h2>Section III</h2></header>
    <section>
      <header><h3>Subsection a</h3></header>
    </section>
  </section>
</article>
<footer>
  <header><h2>Footer</h2></header>
</footer>

Example 03: Outline

  1. Header

    1. Navigation
    2. Main

      1. Section I
      2. Section II

        1. Subsection a
        2. Subsection b
      3. Section III

        1. Subsection a
    3. Aside
  2. Footer

View example 03

After that, I was totally confused and decided, to sort it out step by step.
That procedure finally gave me the clue, I want to share with you now.

Step by Step (Uh Baby!)

Step I: Investigate the Structured Part

Let us start with the strictly structured part of the document: the article and it’s subsections.
At first a minimal example with no markup except the article– and the section-tags:

Example 04: Markup


<!DOCTYPE html>
<title>Example 04</title>
<article>
  Main
  <section>
    Section I
  </section>
  <section>
    Section II
    <section>
      Subsection a
    </section>
    <section>
      Subsection b
    </section>
  </section>
  <section>
    Section III
    <section>
      Subsection a
    </section>
  </section>
</main>

Example 04: Outline

  1. Untitled BODY

    1. Untitled ARTICLE

      1. Untitled SECTION
      2. Untitled SECTION

        1. Untitled SECTION
        2. Untitled SECTION
      3. Untitled SECTION

        1. Untitled SECTION

View Example 04

Nothing really unexpected here.
The article– and section-tags are reflected in the outline according to their nesting.
The only thing notably here is, that the body itself is also reflected in the outline.
It appears on its own level as the root-element of all tags.
We can think of it as the title of our document.

We can add headings of any kind (h1h6) here and will always get an identically structured outline, that reflects the text of our headings.
If we want to give the body a title, we have to place a heading outside and before any sectioning-elements:

Example 05: Markup


<!DOCTYPE html>
<title>Example 05</title>
<h1>Page</h1>
<article>
  <h1>Article</h1>
  <section>
    <h1>Section I</h1>
  </section>
  <section>
    <h1>Section II</h1>
    <section>
      <h1>Subsection a</h1>
    </section>
    <section>
      <h1>Subsection b</h1>
    </section>
  </section>
  <section>
    <h1>Section III</h1>
    <section>
      <h1>Subsection a</h1>
    </section>
  </section>
</article>

Example 05: Outline

  1. Page

    1. Article

      1. Section I
      2. Section II

        1. Subsection a
        2. Subsection b
      3. Section III

        1. Subsection a

View Example 05

This is the new part of the outline algorithm introduced in HTML5: The nesting of elements, that define sections, defines the outline of the document.
The rank of the heading element is ignored by this algorithm!

Among the elements, that define sections in HTML5 are the article and the section tags.
But there are more.
I will discuss them later.
For now, you only have to know, that in HTML5, sectioning elements define the structure of the outline.
Also, you should memorize, that the outline always has a single root without any siblings: the body.

Step II: Investigate the Page-Elements

So, let us do the same with the tags that represent the different logical sections of a web-page: the page-elements.
We start with a minimal example again, that contains no markup except the header– the main and the footer-tags:

Example 06: Markup


<!DOCTYPE html>
<title>Example 06</title>
<header>Page</header>
<main>Main</main>
<footer>Footer</footer>

Example 06: Outline

  1. Untitled BODY

View Example 06

That is wired, ehh?
There is only one untitled element in the outline.
The explanation for this is, that neither the header– nor the main– nor the footer-tag belong to the elements, that define a section in HTML5!
This is often confused, because these elements define the logical sections (header – main-content – footer) of a website.
But these logical sections do not have to do anything with the structural sectioning of the document, that defines the outline.

Step III: Investigate the Headings

So, what happens, if we add the desired markup for our headings?
We want a h1-heading for our main-content, because it is the important part of our page.
The header should have a h2-heading and the footer a h3-heading, because it is rather unimportant.

Example 07: Markup


<!DOCTYPE html>
<title>Example 07</title>
<header><h2>Page</h2></header>
<main><h1>Main</h1></main>
<footer><h3>Footer</h3></footer>

Example 07: Outline

  1. Page
  2. Main

    1. Footer

View Example 07

Now, there is an outline again.
But why?
And why is it looking this way?

What happens here, is implicit sectioning.
In short, implicit sectioning is the outline algorithm of HTML4.
HTML5 needs implicit sectioning, to keep compatible with HTML4, which still dominates the web.
In fact, we could have used plain HTML4, with div instead of header, main and footer, and it would have yield the exact same outline:

Example 08: Markup


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head><title>Example 08</title></head>
  <body>
    <div class="header"><h2>Page</h2></div>
    <div class="main"><h1>Main</h1></div>
    <div class="footer"><h3>Footer</h3></div>
  </body>
</html>

Example 08: Outline

  1. Page
  2. Main

    1. Footer

View Example 08

In HTML4, solely the headings (h1h6) define the outline of a document.
The enclosing elements or any nesting of them are ignored altogether.
The level, at which a heading appears in the outline, is defined by the rank of the heading alone.
(Strictly speaking, HTML4 does not define anything like a document outline.
But as a result of the common usage and interpretation, this is, how people outline their documents with HTML4.)

The implicit sectioning of HTML5 works in a way, that is backward compatible with this way of outlining, but closes the gaps in the resulting hierarchy:
Each heading implicitly opens a section – hence the name –, but if there is a gap between its rank and the rank of its ancestor – that is the last preceding heading with a higher rank – it is placed in the level directly beneath its ancestor:

Example 09: Markup


<!DOCTYPE html>
<title>Example 09</title>
<h4>h4</h4>
<h2>h2</h2>
<h4>h4</h4>
<h3>h3</h3>
<h2>h2</h2>
<h1>h1</h1>
<h2>h2</h2>
<h3>h3</h3>

Example 09: Outline

  1. h4
  2. h2

    1. h4
    2. h3
  3. h2
  4. h1

    1. h2

      1. h3

View Example 09

See, how the first heading h4 ends up on the same level as the second, which is a h2.
Or, how the third and fourth headings are both on the same level under the h2, although they are of different rank.
And note, how the h2 and h3 end up on different sectioning-levels as their earlier appearances, if they follow a h1 in the natural order.

Step IV: Mixing it all together

With the gathered clues in mind, we can now retry to layout our document with the desired outline.
If we want, that Header, Main and Footer end up as top level citizens in our planed outline, we simply have to achieve, that they are all recognized as sections under the top level by the HTML5 outline algorithm.
We can do that, by explicitly stating, that the header and the footer are section:

Example 10: Markup


<!DOCTYPE html>
<title>Example 10</title>
<header>
  <section>
    <h2>Main</h2>
  </section>
</header>
<main>
  <article>
    <h1>Article</h1>
    <section>
      <h2>Section I</h2>
    </section>
    <section>
      <h2>Section II</h2>
      <section>
        <h3>Subsection a</h3>
      </section>
      <section>
        <h3>Subsection b</h3>
      </section>
    </section>
    <section>
      <h2>Section III</h2>
      <section>
        <h3>Subsection a</h3>
      </section>
    </section>
  </article>
</main>
<footer>
  <section>
    <h3>Footer</h3>
  </section>
</footer>

Example 10: Outline

  1. Untitled BODY

    1. Main
    2. Article

      1. Section I
      2. Section II

        1. Subsection a
        2. Subsection b
      3. Section III

        1. Subsection a
    3. Footer

View Example 10

So far, so good.
But what about the untitled body?
We forgot about the single root of any outline, that is defined by the body, how we learned back in step 1. As shown in example 05, we can simply name that by putting a heading outside and before any element, that defines a section:

Example 11: Markup


<!DOCTYPE html>
<title>Example 11</title>
<header>
  <h2>Page</h2>
  <section>
    <h3>Header</h3>
  </section>
</header>
<main>
  <article>
    <h1>Article</h1>
    <section>
      <h2>Section I</h2>
    </section>
    <section>
      <h2>Section II</h2>
      <section>
        <h3>Subsection a</h3>
      </section>
      <section>
        <h3>Subsection b</h3>
      </section>
    </section>
    <section>
      <h2>Section III</h2>
      <section>
        <h3>Subsection a</h3>
      </section>
    </section>
  </article>
</main>
<footer>
  <section>
    <h3>Footer</h3>
  </section>
</footer>

Example 11: Outline

  1. Page

    1. Header
    2. Main

      1. Section I
      2. Section II

        1. Subsection a
        2. Subsection b
      3. Section III

        1. Subsection a
    3. Footer

View Example 11

Step V: Be Aware, Which Elements Define Sections

The eagle-eyed among you might have noticed, that I had “forgotten” the two element-types nav and aside, when we were investigating the elements, that define the logical structure of the page in step 2.
I did not forgot about these – I left them out intentionally.
Because otherwise, the results of example 07 would have been too confusing, to made my point about implicit sectioning.
Let us look, what would have happend:

Example 12: Markup


<!DOCTYPE html>
<title>Example 12</title>
<header>
  <h1>Page</h1>
  <nav><h1>Navigation</h1></nav>
</header>
<main><h1>Main</h1></main>
<aside><h1>Aside</h1></aside>
<footer><h1>Footer</h1></footer>

Example 07: Outline

  1. Page

    1. Navigation
  2. Main

    1. Aside
  3. Footer

View Example 12

What is wrong there?
Why are Navigation and Aside showing up as children, albeit we marked up every element with headings of the same rank?
The reason for this is, that nav and aside are sectioning elements:

Example 12: Markup


<!DOCTYPE html>
<title>Example 13</title>
<header>
  Page
  <nav>Navigation</nav>
</header>
<main>Main</main>
<aside>Aside</aside>
<footer>Footer</footer>

Example 07: Outline

  1. Untitled BODY

    1. Untitled NAV
    2. Untitled ASIDE

View Example 13

The HTML5 spec defines four sectioning elements: article, section, nav and aside!
Some explain the confusion about this fact with the constantly evolving standard, that leads to structurally unclear specifications.
I will be frank:
I cannot imagine any good reason for this decision!
In my opinion, the concept would be much clearer, if article and section would be the only two sectioning elements and nav and aside would only define the logical structure of the page, like header and footer.

Putting It All Together

Knowing, that nav and aside will define sections, we now can complete our outline skillfully avoiding the appearance of untitled sections:

Example 14: Markup


<!DOCTYPE html>
<title>Example 14</title>
<header>
  <h2>Page</h2>
  <section>
    <h3>Header</h3>
    <nav><h4>Navigation</h4></nav>
  </section>
</header>
<main>
  <article>
    <h1>Main</h1>
    <section>
      <h2>Section I</h2>
    </section>
    <section>
      <h2>Section II</h2>
      <section>
        <h3>Subsection a</h3>
      </section>
      <section>
        <h3>Subsection b</h3>
      </section>
    </section>
    <section>
      <h2>Section III</h2>
      <section>
        <h3>Subsection a</h3>
      </section>
    </section>
  </article>
</main>
<aside><h3>Aside</h3></aside>
<footer>
  <section>
    <h3>Footer</h3>
  </section>
</footer>

Example 14: Outline

  1. Page

    1. Header

      1. Navigation
    2. Main

      1. Section I
      2. Section II

        1. Subsection a
        2. Subsection b
      3. Section III

        1. Subsection a
    3. Aside
    4. Footer

View Example 14

Et voilĂ : Our Perfect Outline!

If you memorize the concepts, that you have learned in this little tutorial, you should now be able to mark up your documents to generate your perfect outline

…but: one last word about headings:

A Word On The Ranks Of The Headings

It is crucial to note, that the new outline-algorithm still is a fiction: most user agents do not implement the algorithm yet.
Hence, you still should stick to the old hints for keeping your content accessible and point out the most important heading to the search engines.

But there is no reason, not to apply the new possibilities shown in this article to your markup: it will only make it more feature-proof.
It is very likely, that search engines will start to adopt the HTML5 outline algorithm, to make more sense out of your content in near feature – or are already doing so…
So, why not be one of the first, to gain from that new technique.

I would advise you, to adopt the new possibilities to section your content and generate a sensible outline, while still keeping the old heading ranks to be backward compatible.

hibernate4-maven-plugin 1.1.0 released!

Today we released the version 1.1.0 of hibernate4-maven-plugin to Central!

The main work in this release were modification to the process of configuration-gathering.
The plugin now also is looking for a hibernate.cfg.xml on the classpath or a persistence-unit specified in a META-INF/persistence.xml.

With this enhancement, the plugin is now able to deal with all examples from the official
Hibernate Getting Started Guide.

All configuration infos found are merged together with the same default precedences applied by hibernate.
So, the overall order, in which possible configuration-sources are checked is now (each later source might overwrite settings of a previous source):

  1. hibernate.properties
  2. hibernate.cfg.xml
  3. persistence.xml
  4. maven properties
  5. plugin configuration

Because the possible new configuration-sources might change the expected behavior of the plugin, we lifted the version to 1.1.

This release also fixes a bug, that occured on some platforms, if the path to the project includes one or more space characters.

Release notes:


commit 94e6b2e93fe107e75c9d20aa1eb3126e78a5ed0a
Author: Kai Moritz
Date: Sat May 16 14:14:44 2015 +0200

Added script to check outcome of the hibernate-tutorials

commit b3f8db2fdd9eddbaac002f94068dd1b4e6aef9a8
Author: Kai Moritz
Date: Tue May 5 12:43:15 2015 +0200

Configured hibernate-tutorials to use the plugin

commit 4b6fc12d443b0594310e5922e6ad763891d5d8fe
Author: Kai Moritz
Date: Tue May 5 12:21:39 2015 +0200

Fixed the settings in the pom's of the tutorials

commit 70bd20689badc18bed866b3847565e1278433503
Author: Kai Moritz
Date: Tue May 5 11:49:30 2015 +0200

Added tutorials of the hibernate-release 4.3.9.Final as integration-tests

commit 7e3e9b90d61b077e48b59fc0eb63059886c68cf5
Author: Kai Moritz
Date: Sat May 16 11:04:36 2015 +0200

JPA-jdbc-properties are used, if appropriate hibernate-properties are missing

commit c573877a186bec734915fdb3658db312e66a9083
Author: Kai Moritz
Date: Thu May 14 23:43:13 2015 +0200

Hibernate configuration is gathered from class-path by default

commit 2a85cb05542795f9cd2eed448f212f92842a85e8
Author: Kai Moritz
Date: Wed May 13 09:44:18 2015 +0200

Found no way to check, that mapped classes were found

commit 038ccf9c60be6c77e2ba9c2d2a2a0d261ce02ccb
Author: Kai Moritz
Date: Tue May 12 22:13:23 2015 +0200

Upgraded scannotation from 1.0.3 to 1.0.4

This fixes the bug that occures on some platforms, if the path contains a
space. Created a fork of scannotation to bring the latest bug-fixes from SVN
to maven central...

commit c43094689043d7da04df6ca55529d0f0c089d820
Author: Kai Moritz
Date: Sun May 10 19:06:27 2015 +0200

Added javadoc-jar to deployed artifact

commit 524cb8c971de87c21d0d9f0e04edf6bd30f77acc
Author: Kai Moritz
Date: Sat May 9 23:48:39 2015 +0200

Be sure to relase all resources (closing db-connections!)

commit 1e5cca792c49d60e20d7355eb97b13d591d80af6
Author: Kai Moritz
Date: Sat May 9 22:07:31 2015 +0200

Settings in a hibernate.cfg.xml are read

commit 9156c5f6414b676d34eb0c934e70604ba822d09a
Author: Kai Moritz
Date: Tue May 5 23:42:40 2015 +0200

Catched NPE, if hibernate-dialect is not set

commit 62859b260a47e70870e795304756bba2750392e3
Author: Kai Moritz
Date: Sun May 3 18:53:24 2015 +0200

Upgraded oss-type, maven-plugin-api and build/report-plugins

commit c1b3b60be4ad2c5c78cb1e3706019dfceb390f89
Author: Kai Moritz
Date: Sun May 3 18:53:04 2015 +0200

Upgraded hibernate to 4.3.9.Final

commit 038ccf9c60be6c77e2ba9c2d2a2a0d261ce02ccb
Author: Kai Moritz
Date: Tue May 12 22:13:23 2015 +0200

Upgraded scannotation from 1.0.3 to 1.0.4

This fixes the bug that occures on some platforms, if the path contains a
space. Created a fork of scannotation to bring the latest bug-fixes from SVN
to maven central...

commit c43094689043d7da04df6ca55529d0f0c089d820
Author: Kai Moritz
Date: Sun May 10 19:06:27 2015 +0200

Added javadoc-jar to deployed artifact

commit 524cb8c971de87c21d0d9f0e04edf6bd30f77acc
Author: Kai Moritz
Date: Sat May 9 23:48:39 2015 +0200

Be sure to relase all resources (closing db-connections!)

commit 1e5cca792c49d60e20d7355eb97b13d591d80af6
Author: Kai Moritz
Date: Sat May 9 22:07:31 2015 +0200

Settings in a hibernate.cfg.xml are read

commit 9156c5f6414b676d34eb0c934e70604ba822d09a
Author: Kai Moritz
Date: Tue May 5 23:42:40 2015 +0200

Catched NPE, if hibernate-dialect is not set

commit 62859b260a47e70870e795304756bba2750392e3
Author: Kai Moritz
Date: Sun May 3 18:53:24 2015 +0200

Upgraded oss-type, maven-plugin-api and build/report-plugins

commit c1b3b60be4ad2c5c78cb1e3706019dfceb390f89
Author: Kai Moritz
Date: Sun May 3 18:53:04 2015 +0200

Upgraded hibernate to 4.3.9.Final

commit 038ccf9c60be6c77e2ba9c2d2a2a0d261ce02ccb
Author: Kai Moritz
Date: Tue May 12 22:13:23 2015 +0200

Upgraded scannotation from 1.0.3 to 1.0.4

This fixes the bug that occures on some platforms, if the path contains a
space. Created a fork of scannotation to bring the latest bug-fixes from SVN
to maven central...

commit c43094689043d7da04df6ca55529d0f0c089d820
Author: Kai Moritz
Date: Sun May 10 19:06:27 2015 +0200

Added javadoc-jar to deployed artifact

commit 524cb8c971de87c21d0d9f0e04edf6bd30f77acc
Author: Kai Moritz
Date: Sat May 9 23:48:39 2015 +0200

Be sure to relase all resources (closing db-connections!)

commit 1e5cca792c49d60e20d7355eb97b13d591d80af6
Author: Kai Moritz
Date: Sat May 9 22:07:31 2015 +0200

Settings in a hibernate.cfg.xml are read

commit 9156c5f6414b676d34eb0c934e70604ba822d09a
Author: Kai Moritz
Date: Tue May 5 23:42:40 2015 +0200

Catched NPE, if hibernate-dialect is not set

commit 62859b260a47e70870e795304756bba2750392e3
Author: Kai Moritz
Date: Sun May 3 18:53:24 2015 +0200

Upgraded oss-type, maven-plugin-api and build/report-plugins

commit c1b3b60be4ad2c5c78cb1e3706019dfceb390f89
Author: Kai Moritz
Date: Sun May 3 18:53:04 2015 +0200

Upgraded hibernate to 4.3.9.Final

commit 248ff3220acc8a2c11281959a1496adc024dd4df
Author: Kai Moritz
Date: Sun May 3 18:09:12 2015 +0200

Renamed nex release to 1.1.0

commit 2031d4cfdb8b2d16e4f2c7bbb5c03a15b4f64b21
Author: Kai Moritz
Date: Sun May 3 16:48:43 2015 +0200

Generation of tables and rows for auditing is now default

commit 42465d2a5e4a5adc44fbaf79104ce8cc25ecd8fd
Author: Kai Moritz
Date: Sun May 3 16:20:58 2015 +0200

Fixed mojo to scan for properties in persistence.xml

commit d5a4326bf1fe2045a7b2183cfd3d8fdb30fcb406
Author: Kai Moritz
Date: Sun May 3 14:51:12 2015 +0200

Added an integration-test, that depends on properties from a persistence.xml

commit 5da1114d419ae10f94a83ad56cea9856a39f00b6
Author: Kai Moritz
Date: Sun May 3 14:51:46 2015 +0200

Switched to usage of a ServiceRegistry

commit fed9fc9e4e053c8b61895e78d1fbe045fadf7348
Author: Kai Moritz
Date: Sun May 3 11:42:54 2015 +0200

Integration-Test for envers really generates the SQL

commit fee05864d61145a06ee870fbffd3bff1e95af08c
Author: Kai Moritz
Date: Sun Mar 15 16:56:22 2015 +0100

Extended integration-test "hib-test" to check for package-level annotations

commit 7518f2a7e8a3d900c194dbe61609efa34ef047bd
Author: Kai Moritz
Date: Sun Mar 15 15:42:01 2015 +0100

Added support for m2e

Thanks to Andreas Khutz

Replace text by graphic without extra markup

Here is a little trick for you, to replace text by a graphic through pure CSS without the need to add extra markup:


SELECTOR
{
  text-indent: -99em;
  line-height: 0;
}
SELECTOR:after
{
  display: block;
  text-indent: 0;
  content: REPLACEMENT;
}

SELECTOR can be any valid CSS-selector.
REPLACEMENT references the graphic, which should replace the text.
This can be a SVG-graphic, a vector-graphics from a font, any bitmap graphic or (quiet useless, but a simple case to understand the source like in the first of my two examples) other text.
SVG- and bitmap-graphics are simply referred by an url in the content-directive, like I have done it with a data-url in my second example.
For the case of an icon embedded in a vector you simply put the character-code of the icon in the content-directive, like described in the according ALA-article.

Examples

  1. Example 1
  2. Example 2

What is it good for?

If you need backward compatibility for Internet Explorer 8 and below or Android 2.3 and below, you have to use icon-fonts to support these old browsers.
I use this often, if I have a brand logo, that should be inserted in a accessible way and do not want to bloat up the html-markup with useless tag’s, to achieve this.

Logging Request- and Response-Data From Requets Made Through RestTemplate

Logging request- and response-data for requests made through Spring’s RestTemplate is quite easy, if you know, what to do.
But it is rather hard, if you have no clue where to start.
Hence, I want to give you some hints in this post.

In its default configuration, the RestTemplate uses the HttpClient of the Apache HttpComponents package.
You can verify this and the used version with the mvn-command


mvn dependency:tree

To enable for example logging of the HTTP-Headers send and received, you then simply can add the following to your logging configuration:


<logger name="org.apache.http.headers">
  <level value="debug"/>
</logger>

Possible Pitfalls

If that does not work, you should check, which version of the Apache HttpComponents your project actually is using, because the name of the logger has changed between version 3.x and 4.x.
Another common cause of problems is, that the Apache HttpComponets uses Apache Commons Logging.
If the jar for that library is missing, or if your project uses another logging library, the messages might get lost because of that.

hibernate4-maven-plugin 1.0.5 released!

Today we released the version 1.0.5 of hibernate4-maven-plugin to Central!

This release mainly fixes a NullPointerException-bug, that was introduced in 1.0.4.
The NPE was triggered, if a hibernate.properties-file is present and the dialect is specified in that file and not in the plugin configuration.
Thanks to Paulo Pires and and everflux, for pointing me at that bug.

But there are also some minor improvements to talk about:

  • Package level annotations are now supported (Thanks to Joachim Van der Auwera for that)
  • Hibernate Core was upgraded to 4.3.7.Final
  • Hibernate Envers was upgraded to 4.3.7.Final
  • Hibernate Validator was upgrades to 5.1.3.Final

The upgrade of Hibernate Validator is a big step, because 5.x supports Bean Validation 1.1 (JSR 349).
See the FAQ of hibernate-validator for more details on this.

Because Hibernate Validator 5 requires the Unified Expression Language (EL) in version 2.2 or later, a dependency to javax.el-api:3.0.0 was added.
That does the trick for the integration-tests included in the source code of the plugin.
But, because I am not using Hibernate Validator in any of my own projects, at the moment, the upgrade may rise some backward compatibility errors, that I am not aware of.
If you stumble across any problems, please let me know!

Release notes:


commit ec30af2068f2d12a9acf65474ca1a4cdc1aa7122
Author: Kai Moritz
Date: Tue Nov 11 15:28:12 2014 +0100

[maven-release-plugin] prepare for next development iteration

commit 18840e3c775584744199d8323eb681b73b98e9c4
Author: Kai Moritz
Date: Tue Nov 11 15:27:57 2014 +0100

[maven-release-plugin] prepare release hibernate4-maven-plugin-1.0.5

commit b95416ef16bbaafecb3d40888fe97e70cdd75c77
Author: Kai Moritz
Date: Tue Nov 11 15:10:32 2014 +0100

Upgraded hibernate-validator from 4.3.2.Final to 5.1.3.Final

Hibernate Validator 5 requires the Unified Expression Language (EL) in
version 2.2 or later. Therefore, a dependency to javax.el-api:3.0.0 was
added. (Without that, the compilation of some integration-tests fails!)

commit ad979a8a82a7701a891a59a183ea4be66672145b
Author: Kai Moritz
Date: Tue Nov 11 14:32:42 2014 +0100

Upgraded hibernate-core, hibernate-envers, hibernate-validator and maven-core

* Upgraded hibernate-core from 4.3.1.Final to 4.3.7.Final
* Upgraded hibernate-envers from 4.3.1.Final to 4.3.7.Final
* Upgraded hibernate-validator from 4.3.1.Final to 4.3.2.Final
* Upgraded maven-core from 3.2.1 to 3.2.3

commit 347236c3cea0f204cefd860c605d9f086e674e8b
Author: Kai Moritz
Date: Tue Nov 11 14:29:23 2014 +0100

Added FAQ-entry for problem with whitespaces in the path under Windows

commit 473c3ef285c19e0f0b85643b67bbd77e06c0b926
Author: Kai Moritz
Date: Tue Oct 28 23:37:45 2014 +0100

Explained how to suppress dependency-scanning in documentation

Also added a test-case to be sure, that dependency-scanning is skipped, if
the parameter "dependencyScanning" is set to "none".

commit 74c0dd783b84c90e116f3e7f1c8d6109845ba71f
Author: Kai Moritz
Date: Mon Oct 27 09:04:48 2014 +0100

Fixed NullPointerException, when dialect is specified in properties-file

Also added an integration test-case, that proofed, that the error was
solved.

commit d27f7af23c82167e873ce143e50ce9d9a65f5e61
Author: Kai Moritz
Date: Sun Oct 26 11:16:00 2014 +0100

Renamed an integration-test to test for whitespaces in the filename

commit 426d18e689b89f33bf71601becfa465a00067b10
Author: Kai Moritz
Date: Sat Oct 25 17:29:41 2014 +0200

Added patch by Joachim Van der Auwera to support package level annotations

commit 3a3aeaabdb1841faf5e1bf8d220230597fb22931
Author: Kai Moritz
Date: Sat Oct 25 16:52:34 2014 +0200

Integrated integration test provided by Claus Graf (clausgraf@gmail.com)

commit 3dd832edbd50b1499ea6d53e4bcd0ad4c79640ed
Author: Kai Moritz
Date: Mon Jun 2 10:31:13 2014 +0200

[maven-release-plugin] prepare for next development iteration

Running aspectj-maven-plugin with the current Version 1.8.1 of AspectJ

Lately, I stumbled over a syntactically valid class, that can not be compiled by the aspectj-maven-plugin, even so it is a valid Java-7.0 class.

Using the current version (Version 1.8.1) of AspectJ solves this issue.
But unfortunatly, there is no new version of the aspectj-maven-plugin available, that uses this new version of AspectJ.
The last version of the aspectj-maven-plugin was released to Maven Central on December the 4th 2013 and this versions is bundeled with the version 1.7.2 of AspectJ.

The simple solution is, to bring the aspectj-maven-plugin to use the current version of AspectJ.
This can be done, by overwriting its dependency to the bundled aspectj.
This definition of the plugin does the trick:


<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>aspectj-maven-plugin</artifactId>
  <version>1.6</version>
  <configuration>
    <complianceLevel>1.7</complianceLevel>
    <aspectLibraries>
      <aspectLibrary>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
      </aspectLibrary>
    </aspectLibraries>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>compile</goal>
      </goals>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjtools</artifactId>
      <version>1.8.1</version>
    </dependency>
  </dependencies>
</plugin>

The crucial part is the explicit dependency, the rest depends on your project and might have to be adjusted accordingly:


  <dependencies>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjtools</artifactId>
      <version>1.8.1</version>
    </dependency>
  </dependencies>

I hope, that helps, folks!

aspectj-maven-plugin can not compile valid Java-7.0-Code

I stumbled over a valid construction, that can not be compiled by the aspectj-maven-plugin:


class Outer
{
  void outer(Inner inner)
  {
  }

  class Inner
  {
    Outer outer;

    void inner()
    {
      outer.outer(this);
    }
  }
}

This code might look very useless.
Originally, it Inner was a Thread, that wants to signal its enclosing class, that it has finished some work.
I just striped down all other code, that was not needed, to trigger the error.

If you put the class Outer in a maven-project and configure the aspectj-maven-plugin to weave this class with compliance-level 1.6, you will get the following error:


[ERROR] Failed to execute goal org.codehaus.mojo:aspectj-maven-plugin:1.6:compile (default-cli) on project shouter: Compiler errors:
[ERROR] error at outer.inner(this);
[ERROR] 
[ERROR] /home/kai/juplo/shouter/src/main/java/Outer.java:16:0::0 The method inner(Outer.Inner) is undefined for the type Outer
[ERROR] error at queue.done(this, System.currentTimeMillis() - start);
[ERROR] 

The normal compilation works, because the class is syntactically correct Java-7.0-Code.
But the AspectJ-Compiler (Version 1.7.4) bundeled with the aspectj-maven-pluign will fail!

Fortunately, I found out, how to use the aspectj-maven-plugin with AspectJ 1.8.3.

So, if you have a similar problem, read on…