Asciidoctor maven integration : introduction to asciidoctor and maven asciidoctor plugin part 2/2

This is the second part of the Asciidoctor maven integration tutorial part 1/2 where we explore some of Asciidoctor cool features

4. Additional cool formatting elements and content

There are plenty of nice cheat-sheets out there that resume much better all the cool stuff you can do with (see 5. Some useful links) so I will just list here a few tips to get you started

4a. Asciidoc files inclusion or composition

Personally when writing documentation I like to create a separate file for each topic and then include them in an a big index file (you can do this otherwise if you prefer) this can easily be done using the include macro

Let's create a new Asciidoc page named topic1 and add some content to it

= Topic 1

== Intro

This page describes some information related to topic1

and now include the newly created page using the include macro

= Asciidoctor hello world



include::topic1.ad[]

After re-compiling the code you should end up with the content of the file topic1.ad inside the index.html file

4b. Table of contents (TOC)

Asciidoctor has a lot of macros and attributes that help you when writing documentation, the full list of attributes can be found here

Attributes are configured as child tags of the attributes XML tag under the maven asciidoctor plugin. To enable the table of contents while providing a TOC level we will use the toclevels attribute, since once you start writing a lot of documentation you could end up with a pretty big HTML document it's a good idea to enable the creation of anchors using the setanchors attribute



  
     
          org.asciidoctor
          asciidoctor-maven-plugin
          ${version.asciidoctor}
          
              
                 output-html
                 generate-resources
                 
                     process-asciidoc
                 
                 
                     html
                     book                    
                     
                          
                          true
                          
                          3
                     
                 

               
           
      
  


Once you configured the maven plugin it's time to add the :toc: attribute to the index.ad header

Please be aware within the the first lines of a document known as document header spacing and markup are important as they have special meaning and are handled differently by the asciidoc parsing engine

, for more information on the document header please check the documentation here

= Asciidoctor hello world
:toc:


include::topic1.ad[]

Once the documentation files generated the result should be pretty close to the one in the picture below :

Please note : Not all attributes are supported through the maven asciidoctor plugin so you have to play a bit with the maven configuration to see which ones are supported.
4c. Adding images in your documentation

Everyone knows a picture is worth 1000 words so why don't add some pretty pictures to your documentation

By default when generating the documentation files containing images the asciidoctor plugin will prefix all image paths with images/ this of course can be changed but I usually leave it with the default option

We will now add an images folder to our maven project under src/main/resources/images and put an image of your choice inside of it in my case asciidoc-logo.png

Once this is done let's add our image to our document

= Topic 1

== Intro

This page describes some information related to topic1.

Asciidoc is cool

image::asciidoc-logo.png[Asciidoc logo]

Now we have included an image in our doc file but we're not done yet, you need to instruct maven to copy our images folder to the generated-docs target folder

 
...
        
            
                
                src/main/resources/images
                ${build.directory}/generated-docs/images
            
  .....


4d. Code syntax highlighting

Code syntax highlighting is very important when writing documentation since it helps with the readability. Asciidoc currently supports 4 frameworks to handle your code highlighting

  • coderay
  • prettify
  • highlightjs
  • pygments (not currently supported by maven asciidoctor plugin)

For this tutorial let's say we will use coderay so we first need to activate the syntax highlighting in the maven POM file :



  
      
          org.asciidoctor
          asciidoctor-maven-plugin
          ${version.asciidoctor}
          
             
                 output-html
                 generate-resources
                 
                    process-asciidoc
                 
                 
                      
                      coderay
                      html
                      book

                      
                         
                         true
                         3
                     

                 
              
          
       
    
  

Once our maven configuration is done we can add some source code to our docs, the syntax is pretty straightforward in it's most basic form you just put [source, language] and you surround your code with ---- like so :

[source,java]
----
public class HelloWorld{

   public static void main(String[] args){
      System.out.println("Hello World");
   }
}
----

Once your docs file regenerated you should see something like this :

4e. External links (target _blank)

Whenever I'm reading an HTML documentation containing a link I prefer it when the link opens automatically in a new tab i.e.target="_blank"

This can be achieved using link attributes however by default in Asciidoc this feature is disabled; luckily you just need one small line in your pom.xml file to enable this feature with an attribute


  
      
          org.asciidoctor
          asciidoctor-maven-plugin
          ${version.asciidoctor}
          
             
                 output-html
                 generate-resources
                 
                    process-asciidoc
                 
                 
                      
                      coderay
                      html
                      book

                      
                         
                         true
                         3
                         
                        true
                     

                 
              
          
       
    
  

Now you can go ahead an add your links withe


http://powerman.name/doc/asciidoc[Asciidoc cheatsheet, window="_blank"]


So this concludes this 2 part introductory tutorial to Asciidoctor and maven integration ; have fun writing cool documentation!

5. Some useful links

As usual you can find the code source for this tutorial over github here

Below is a list of useful links to help you with Asciidoctor such as cheatsheet or general documentation :

Asciidoctor maven integration : introduction to asciidoctor and integration with maven asciidoctor plugin part 1/2

For some time now I have been hearing a lot aboutAsciiDoc as a mean to write documentation but never had the chance to use it...

Recently I stumbled upon AsciiDoctor and since I was about to begin working on a small project with no previous documentation I thought it was the perfect time to try it out..

Documentation is an important part of a project which more often than we would like gets put aside for a great number of reasons. One of them is that we as developpers tend not to like writing documentation...

0.Intro and scope

In this tutorial I will show you how to integrate Asciidoctor class in your Java project and get you started with a small documentation example as well as some tips such as :

  • Asciidoc templating using fragments
  • Generating a TOC (table of contents) for your documentation
  • Integrating images in your asciidoc files
  • Code syntax highlighting in your asciidoc files
  • Making external links (i.e. _target blank)

Please note that I assume you have some knowledge of Asciidoc so I won't delve into much detail regarding Asciidoc

1. What is AsciiDoc ?

AsciiDoc is a text document format for writing notes, documentation, articles, books, ebooks, slideshows, web pages, man pages and blogs. AsciiDoc files can be translated to many formats including HTML, PDF, EPUB, man page. AsciiDoc is highly configurable: both the AsciiDoc source file syntax and the backend output markups (which can be almost any type of SGML/XML markup) can be customized and extended by the user.

2. What is Asciidoctor ?

Asciidoctor is a pure Ruby processor for converting AsciiDoc source files and strings into HTML 5, DocBook 4.5 and other formats. It’s published as a RubyGem and is available under the MIT open source license.

I invite you to take a look to this nice presentation by Dan Allen Discover Zen Writing with Asciidoc which gives you a good overview of AsciiDoc

3. First steps and configuration

First things first go ahead and create a simple maven module let's say a simple JAR for example using the maven archetype plugin or using you favorite IDE

mvn archetype:generate -DgroupId=com.ufasoli -DartifactId=asciidoc-helloworld -DinteractiveMode=false

Once your maven project is created go ahead and create a folder named asciidoc under src/main this is where we will be putting our Asciidoc files

Let's go ahead and create our first asciidoc file under the folder we just created let's name it index.ad and for the moment keep it simple let's just add the page title

= Asciidoctor hello world

So now with our first asciidoc file let's go ahead and configure maven to parse our documentation files and generate HTML documentation files by using the Maven Asciidoctor plugin




  
     
          org.asciidoctor
          asciidoctor-maven-plugin
          ${version.asciidoctor}
          
              
                 output-html
                 generate-resources
                 
                     process-asciidoc
                 
                 
                     html
                     book                    
                 
               
           
      
  

Now if you run a mvn clean compile you will see an index.html that will be generated under the target/generated-docs folder with an output similar to :

So that's it for the first part of this tutorial, you can find the rest tomorrow on part 2

Java Mail network is unreacheable connect exception

Recently I stumbled upon a weird problem while debugging a simple java application that needed to send an email

Since I was debbuging this application locally I used the FakeSMTP tool that I described in this tutorial here : Testing email sending functionality with FakeSMTP which I run locally on my machine

So after editing the configuration on my Java program and firing up the SMTP server I was quite surprised to get the following exception :

Caused by: javax.mail.MessagingException: Could not connect to SMTP host: 127.0.0.1, port: 25 (java.net.SocketException: Network is unreachable: connect)
System.setProperty("java.net.preferIPv4Stack" , "true");

So once you are sure you problem is not coming from a non running SMTP server or a network connection, you can check if the culprit is no other than Java

If you read the Oracle documentation here you will see that by default Java prefers IPv6 to IPv4 which is the problem in our case since FakeSMTP binds on IPv4

Luckily there is a way to force Java to prefer IPv4 over IPv6 using the system property java.net.preferIPv4Stack

This can either be done :

  • programmatically
  • using java options

1. Programmatically


 System.setProperty("java.net.preferIPv4Stack" , "true");

2. Using java options


java -jar myJar.jar -Djava.net.preferIPv4Stack=true

That should take care of the problem

Another solution would be to disable IPv6 networking on your machine but that may have other side effects on your system..

Heroku PostgreSQL and DBVisualiser connection using SSL

I occasionally use Heroku to deploy webapps on the cloud combined with a Postgres database to store my relational data

I recently found a multi-platform polyglot SQL client that I could use with my MAC, this product is called DbVisualiser

However since Heroku requires an SSL security on external connections after providing the usual database connection properties (url, username, password) when I tried to connect through DbVisualiser I was getting the error message :

FATAL: no pg_hba.conf entry for host "86.200.9.63", user "u4b1uljsil33m2", database "de9td8cv06p4se", SSL off

After playing a bit with the different options and reading the Postgres JDBC driver over here I found out that you can provide an Non Validating SSL factory in the connection properties to satisfy Heroku's SSL requirements

In order to configure the SSL properties in DbVisualiser you need to edit the following SSL properties in the Properties tab :

  • SSL : true
  • sslfactory : org.postgresql.ssl.NonValidatingFactory

By providing these 2 properties you should be able to connect to your Heroku database without any problems

SSH linux how to kill an idle or innactive connection

Sometimes when you're disconnected abruptly from a remote server like if your network connection gets dropped, you can be left with a ghost or inactive SSH session.

This can become pretty annoying when you're doing some SSH port redirection since you will not be able to bind to a given port since the ghost connection is still using that port, and you might end up with error messages such as the following :

debug1: Local connections to LOCALHOST:21521 forwarded to remote address localhost:21521
debug1: Local forwarding listening on 127.0.0.1 port 21521.
bind: Address already in use
debug1: Local forwarding listen

Now there are a few ways of dealing with this issue, the one I prefer is a 3 step operation :

1.Check who is connected to the server

This step is actually optional but it allows you to check which user is currently connected to the server and prevent accidentally destroying another user's session (or at least warning him that you will do it ;) )

To check who's connected to the server you can run the w command. the w command shows who is logged in to the system and what they are doing.

So go ahead and run the following command on your prompt :

   [ufasoli]> w

You should see an output similar to this one

 20:16:14 up 132 days,  3:38,  2 users,  load average: 0.04, 0.03, 0.00
USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0     20:07    0.00s  0.02s  0.00s w
root     pts/1     20:09    6:17   0.02s  0.02s -bash

Here you can identify your user with the WHAT column as it indicates what the user is doing (invoking the command w in our case) /

2.Display the running processes

By using the pstree command with the -p to show process identification numbers (PIDs)

Go ahead and run the following command :

[ufasoli]> pstree -p

pstree displays the processes (i.e., executing instances of programs) on the system in the form of a tree diagram so when running the above command you should have an output similar to the one below :

init(1)─┬─cron(8865)
        ├─cupsd(2385)
        ├─oracle(2063)
        ├─oracle(2065)
        ├─oracle(2067)
        ├─oracle(2069)
        ├─oracle(2176)
        ├─oracle(2180)
        ├─oracle(12830)
        ├─scsi_eh_1(226)
        ├─scsi_eh_2(232)
        ├─scsi_eh_3(236)
        ├─slpd(2136)
        ├─sshd(2411)─┬─sshd(12840)───bash(12842)───pstree(12908)
        │            └─sshd(12887)───bash(12889)
        ├─sshd(14276)
        ├─syslogd(2035)
        └─tnslsnr(3917)


3.Kill the unwanted process

In our case the unwanted session has the PID 12287 as it's the session without the pstree command that we've just issued.

You can now kill the unwanted PID (just be careful not to kill a colleagues session ;) ):

   [ufasoli]> kill -1 12887

Once the session is killed you should be able to bind to the previously occupied port

Running a spring boot application with maven

On the last 2 part tutorial that I published recently on Spring boot :Spring boot and spring data (part 1) and Spring boot and spring data (part 2) I said that when using pure maven (not the groovy approach) you needed to either package the project and then run the JAR manually or use the maven mojo exec plugin (which I preferred)

But as often after playing a bit more with it I realized that there is an even simpler solution and that is using the run goal of the spring-boot maven plugin

So you can simply run your spring-boot project by executing the following goal on your console/IDE


 mvn spring-boot:run

Spring boot and spring data jpa tutorial - A sample application using spring 4.0 spring boot and JPA (part 2/2)

This is the second part of the Spring boot and spring data jpa tutorial - A sample application using spring 4.0 spring boot and JPA

At the end of the tutorial I promised you that we will be removing one of the steps when running the application, that is merge the package and run in a maven command and make him do the work

5.- Making maven run the JAR directly

We're going to make maven run the runnable JAR for us after it has been packaged, for this purpose we're going to use one of org.codehaus.mojo maven plugins



....

        
            
                org.springframework.boot
                spring-boot-maven-plugin
            

            
                org.codehaus.mojo
                exec-maven-plugin
                1.2.1
                
                    com.ufasoli.tutorials.spring.boot.HelloWorldApp
                
            
        
    
...

So what's happening here ? :

  • By adding the exec plugin to the build section of our pom.xml and providing a mainClass when we run the appropriate maven goals the application will be packaged and run directly from maven

You can try this by running :

    mvn clean package exec:java

By running this on your console the application will be packaged and run directly using maven

Now let's add some more interesting stuff to our app

6.- Adding Spring Data and JPA support

We're now going to add some Spring Data and JPA support to our app.

The first thing you need to do is add the additional spring boot starter module (spring-boot-starter-data-jpa) to your maven dependencies and since we will be using an embedded HSQL database the dependency for the HSQL driver too:

 
 ...
        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        

         
            hsqldb
            hsqldb
            ${version.hsqldb}
        
...


The next thing you need to do is tell spring to enable Spring Data and its repository features this is done by simply adding the @EnableJpaRepositories to your Spring App class

@ComponentScan 
@EnableAutoConfiguration
@EnableJpaRepositories
public class HelloWorldApp {

    public static void main(String[] args) throws Exception {

        SpringApplication.run(HelloWorldApp.class, args);

    }
}

And that's it if you now build and run your application you will have a Spring web application with Spring Data and JPA support even though the app won't do much for the moment ;).

So what's happening here?

  • Annotating the Spring Application class with the @EnableJpaRepositories will cause a lot of "magic" to happen and a lot of things will be configured/initialized for you such as an Entity Manager, DataSource (see next item), JPA Vendor adapter ..
  • Since we haven't defined a DataSource if Spring finds an in memory JDBC driver in the Classpath it will automatically create one for us using a set of predefined conventions

Now let's add some logic to our app :

7.- Adding some Spring data and JPA logic

The first thing we're going to be doing is adding a simple JPA entity to perform some CRUD operations later on



import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Book {


    @Id
    protected String isbn;
    protected String title;
    protected String author;
    protected String description;
    // omitting setters/getters/constructors
}

So now that we have our entity lets use one of the great features of Spring Data : The Repositories Abstraction :

The goal of Spring Data repository abstraction is to significantly reduce the amount of boilerplate code required to implement data access layers for various persistence stores.

By annotating an interface with @Repository and making this interface extend CrudRepositoryYou will get among other things 2 pretty nifty goodies of the box:

  • Some utility CRUD methods such as findAll() or count()
  • Auto-implementation of methods based on naming convention such as findBooksByAuthor()

And the best part is you get all of this without writing any code logic for these methods (of course you can override these methods, and write some custom methods) as shown in the doc, you can even avoid yet to write some code by using for example the @Query annotation

So now lets create our CRUD repository for our entity with a custom method to find the books by their author


import com.ufasoli.tutorials.spring.boot.model.Book;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;


@Repository
public interface BookRepository extends CrudRepository {

    public Iterable findBooksByAuthor(@Param("author") String author);
}

This interface will be picked up by Spring an instantiated accordingly.

We're almost done with our JPA/database logic, one last thing I would like to do is to have some data inserted automatically into the database when the application starts (especially since we're dealing with an in-memory database

Once again we can take advantage of another Spring convention, if you place a data.sql file in your maven resources directory the script will be automatically executed when the database will be bootstrapped and after reverse engineering your entities into the database

INSERT INTO book(isbn, title, author,description) VALUES ('1111111', 'The Spirit Thief (The Legend of Eli Monpress #1)', 'Rachel Aaron',
                         'Eli Monpress is talented. He''s charming. And he''s a thief.But not just any thief. He''s the greatest thief of the age - and he''s also a wizard. And with the help of his partners - a swordsman with the most powerful magic sword in the world but no magical ability of his own, and a demonseed who can step through shadows and punch through walls - he''s going to put his plan into effect.The first step is to increase the size of the bounty on his head, so he''ll need to steal some big things. But he''ll start small for now. He''ll just steal something that no one will miss - at least for a while. Like a king');

INSERT INTO book(isbn, title, author,description) VALUES ('2222222', 'The Spirit Rebellion (The Legend of Eli Monpress, #2)', 'Rachel Aaron',
                         'Eli Monpress is brilliant. He''s incorrigible. And he''s a thief.He''s also still at large, which drives Miranda Lyonette crazy. While she''s been kicked out of the Spirit Court, Eli''s had plenty of time to plan his next adventure. But now the tables have turned, because Miranda has a new job -- and an opportunity to capture a certain thief. Things are about to get exciting for Eli. He''s picked a winner for his newest heist. His target: the Duke of Gaol''s famous ''thief-proof'' citadel. Eli knows Gaol is a trap, but what''s life without challenges? Except the Duke is one of the wealthiest men in the world, a wizard who rules his duchy with an iron fist, and an obsessive perfectionist with only one hobby: Eli. It seems that everyone is hunting for Eli Monpress');

INSERT INTO book(isbn, title, author,description) VALUES ('3333333', 'The Spirit Eater (The Legend of Eli Monpress, #3)', 'Rachel Aaron',
                         'With the pressure on after his success in Gaol, Eli Monpress, professional thief and degenerate, decides it''s time to lie low for a bit. Taking up residence in a tiny seaside village, Eli and his companions seize the chance for some fun and relaxation. Nico, however, is finding it a bit hard. Plagued by a demon''s voice in her head and feeling powerless, she only sees herself as a burden. Everyone''s holiday comes to an untimely close, though, when Pele arrives to beg Eli''s help for finding her missing father. But there are larger plans afoot than even Eli can see, and the real danger, and the solution, may lie with one of his own and her forgotten past. If only Nico could remember whose side she''s on.');

INSERT INTO book(isbn, title, author,description) VALUES ('4444444', 'The Spirit War (The Legend of Eli Monpress, #4)', 'Rachel Aaron',
                         'Eli Monpress is vain. He''s cocky. And he''s a thief. But he''s a thief who has just seen his bounty topped and he''s not happy about it. The bounty topper, as it turns out, is his best friend, bodyguard, and master swordsman, Josef. Who has been keeping secrets from Eli. Apparently, he''s the only prince of a rather feisty country and his mother (a formidable queen who''s every bit as driven and stubborn as he is) wants him to come home and do his duty, which means throwing over personal ambitions like proving he''s the greatest swordsman who ever lived. Family drama aside, Eli and Josef have their hands full. The Spirit Court has been usurped by the Council of Thrones and someone calling herself the Immortal Empress is staging a massive invasion. But it''s not just politics --- the Immortal Empress has a specific target in mind: Eli Monpress, the greatest thief in the world.');

INSERT INTO book(isbn, title, author,description) VALUES ('5555555', 'Spirit''s End (The Legend of Eli Monpress #5)', 'Rachel Aaron',
                         'First rule of thievery: don''t be a hero. When Eli broke the rules and saved the Council Kingdoms, he thought he knew the price, but resuming his place as the Shepherdess''s favorite isn''t as simple as bowing his head. Now that she has her darling back, Benehime is setting in motion a plan that could destroy everything she was created to protect, and even Eli''s charm might not be enough to stop her. But Eli Monpress always has a plan, and with disaster rapidly approaching, he''s pulling in every favor he can think of to make it work, including the grudging help of the Spirit Court''s new Rector, Miranda Lyonette. But with the world in panic, the demon stirring, and the Lord of Storms back on the hunt, it''s going to take more than luck and charm to pull Eli through this time. He''s going to have to break a few more rules and work with some old enemies if he''s going to survive');

8.- Wrapping things up with a REST controller

To wrap things up we'll add a simple RestController that will interact with our freshly created Repository


import com.ufasoli.tutorials.spring.boot.model.Book;
import com.ufasoli.tutorials.spring.boot.repositories.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController // assumes @ResponseBody annotation in methods annotated with  @RequestMapping
@RequestMapping(value = "/books", produces = MediaType.APPLICATION_JSON_VALUE)
public class BookController {

    @Autowired
    protected BookRepository bookRepository;

    @RequestMapping
    public Iterable books() {
        return bookRepository.findAll(); // uses the findAll() method inherited from CrudRepository
    }


    @RequestMapping(value = "/{isbn}")
    public Book book(@PathVariable("isbn") String isbn) {
        return bookRepository.findOne(isbn);// uses the findOne() method inherited from CrudRepository
    }


    @RequestMapping(value = "/{isbn}", method = RequestMethod.DELETE)
    public String deleteBook(@PathVariable("isbn") String isbn) {

        try {
            bookRepository.delete(isbn);
            return String.format("Book [%s] successfully deleted", isbn);// uses the delete() method inherited from CrudRepository
        } catch (Exception e) {
            return String.format("A problem occurred when deleting Book [%s]", e.getMessage());
        }
    }

    @RequestMapping("/author/{author}")
    public Iterable booksByAuthor(@PathVariable("author") String author) {

        return bookRepository.findBooksByAuthor(author);// uses the custom method defined in our BookRepository interface
    }


}

So that's it you can re-run your application now using the maven goal

     mvn clean package exec:java

You should see your application bootstrapping your database and inserting data, and once it's fully started you should be able to play with your Web Service

9.-Some final thoughts

I must say that I quite enjoyed playing with Spring boot, as long as you're using the full spring stack it helps you get things running quickly and has some very useful starter modules and conventions

I also added the actuator module which gives you some metrics and stats (as REST endpoints) on your application which is pretty cool to have when running the app in production

Check it out here

As usual you can find the code source for this application over at my github account here

OSX show used ports or listening applications with their PID

On OSX you can display applications listening on a given port using the lsof the commands described below will show listening application...