This article shows you step by step how to cache your entire tomcat web application with Squid reverse Proxy without writing any java code.
What is Squid
Squid is a free proxy server for HTTP, HTTPS and FTP which saves bandwidth and increases response time by caching frequently requested web pages. While squid can be used as a proxy server when users try to download pages from the internet, it can be also used as a reverse-proxy by putting squid between the user and your webapp. All user requests first hit Squid. If the requested page already exists in Squid’s cache it is served directly from the cache without hitting your Webapp. If the page does not exist in Squid’s cache, it is fetched from your web application and stored in the cache for future requests.
Squid reduces hits to your server by caching response pages. You don’t have to worry about building page level caching in every application that your write, Squid takes care of that part.
When should I use Squid
Ideally you should use Squid for pages which have a high ratio of reads to writes. In other words, a page that changes less frequently but is accessed very often. Here are some scenarios:
A dynamical web page which displays news and is updated once an hour, and receives hundreds of hits during the hour
A static web page accessed freqently. Squid can give performance boost by caching frequently accessed static web pages in memory
When should I not use Squid
In most cases, if the request URL is the only factor which determines the response then you can safely use Squid. See more specific examples below:
If the entire apps is very dynamic in nature, and the validity of pages changes immediately.
Squid is not suitable for apps which require login. This unfortunately is a large number of applications. Such applications need to resort to back end caching, for example use other caching frameworks like Ehcache to cache re-usable page fragments and/or cache database queries and/or other performance bottlenecks.
Apps which heavily use browser cookies. Squid relies on URLs to cache pages. If the page served is computed from URLs + cookies, then you should not cache those pages in Squid.
How does the overall setup work
Apache Squid Tomcat architecture
Apache receives requests on port 80. Apache calls Squid with the request. Squid checks its cache to see if it has the response cached from before. If yes and if the response is not expired, it returns the cached response.In this case:
Squid will write the following header to the response:
X-Cache: HIT from www.vineetmanohar.com
If the response is not found in Squid’s cache, squid will make a call to Tomcat on port 8082. Tomcat’s proxy connector is listening on this port. It processes the request and sends the response back to Squid. Squid saves the response in its cache, unless caching is disabled for that URL. Squid returns the final response to Apache which sends the response back to the user.
What if I don’t want to use Apache
Using Apache is not required to use Squid. You can run Squid on port 80, and point your users directly to Squid. If that is the case, skip section one and directly jump to section 2 below.
Step 1/3: Apache Httpd Config
If you are using Apache as a front end, you need to instruct Apache to forward requests to Squid at port 3128. See the following code snippet. Change the server name and paths to reflect your real values.
Apache config file:
/etc/httpd/conf/httpd.conf
<VirtualHost x.x.x.x>
ServerName www.vineetmanohar.com
DocumentRoot /home/webadmin/www.vineetmanohar.com/html
# forward requests to squid running on port 3128
ProxyPass / http://localhost:3128/
ProxyPassReverse / http://localhost:3128/
</VirtualHost>
In addition to the above, you also need mod_proxy installed. If you see the following in your httpd.conf, you probably already have mod_proxy installed. If you first need to install mod_proxy.
First make sure that Squid is installed on your server. You can download Squid from here.
The squid config file on Linux/Unix is located at this location.
/etc/squid/squid.conf
The config file is pretty long. Follow these instructions and set the values appropriately.
# leave the port to 3128
http_port 3128
# how much memory cache do you want? depends on how much memory you have on the machine
cache_mem 200 MB
# what's the biggest page that you want stored in memory. If you home page is 100 KB and
# you want it stored in memory, you may set it to a number bigger than that.
maximum_object_size_in_memory 100 KB
# how much disk cache do you want. It is 6400 MB in the following example, change it as per
# your needs. Make sure you have that much disk space free.
cache_dir ufs /var/spool/squid 6400 16 256
# this is probably the most important config section. Here you can configure the cache life for
# each URL pattern.
# Time is in minutes
# 1 day = 1440, 2 days = 2880, 7 days = 10080, 28 days = 40320
# do not cache url1
refresh_pattern ^http://127.0.0.1:8082/url1/ 0 20% 0
# cache url2 for 1 day
refresh_pattern ^http://127.0.0.1:8082/url2/ 1440 20% 1440 override-expire override-lastmod reload-into-ims ignore-reload
# cache css for 7 days
refresh_pattern ^http://127.0.0.1:8082/css 10080 20% 10080 override-expire override-lastmod reload-into-ims ignore-reload
# by default cache the whole website for 1 minute
refresh_pattern ^http://127.0.0.1:8082/ 0 20% 0 override-expire override-lastmod reload-into-ims ignore-reload
# how long should the errors should be cached for. For example 404s, HTTP 500 errors
negative_ttl 0 seconds
# On which host does tomcat run. Set 127.0.0.1 for localhost
httpd_accel_host 127.0.0.1
# this is the proxy port as defined in Tomcat server.xml. By default it is "8082"
httpd_accel_port 8082
# set this to "on". Read more documentation if you want to change this.
httpd_accel_single_host on
# To access Squid stats via the manager interface, you need to enter a password here
cachemgr_passwd your_clear_text_password all
# Say "off" if you want the query string to appear in the squid logs.
strip_query_terms off
Step 3/3: Tomcat Config
Make sure that the HTTP Proxy Connector is defined in TOMCAT_HOME/conf/server.xml.
You can access the Squid config and stats via the Squid Manger HTTP interface. Make sure that the “cachemgr.cgi” file which ships with squid installation is in your cgi-bin directory. More documentation on setting that up here.
Once you’ve set it up, you can access the cache manager via this URL:
http://<hostname>/cgi-bin/cachemgr.cgi
To continue enter the following values:
Cache host: localhost
Cache port: 3128
Manager name: manager
Password: <the value you entered for "cachemgr_passwd" in squid.conf>
Store Directory Stats shows you how much disk space is used by the disk cache.
Cache Client List show you the cache HIT/MISS ratio as %. You should monitor this frequently and tune your cache to get a higher hit %.
Reload Squid Config without restarting
Edit the squid config using “vi” or your favorite editor.
vi /etc/squid/squid.conf
Once you are done editing, reload the new config without restarting Squid.
/usr/sbin/squid -k reconfigure
Clearing Squid Cache
To clear Squid cache:
1) Set the memory cache to 4 MB (or a lower number)
cache_mem 8 MB
2) Set the disk cache to 8 MB (or a lower number). The disk cache must be higher that the memory cache.
cache_dir ufs /var/spool/squid 20 16 256
3) Reload squid config without restart as described in the previous section
4) You may need to wait a few hours for the cache to get cleared. Once the cache is clear, you may restore the previous cache sizes and reload the new config again. You can monitor the cache size through the Squid Manager HTTP interface.
Bypassing Squid
If for some reason you need to bypass Squid, reconfigure Apache to directly send requests to Tomcat. Edit the Apache config file /etc/httpd/conf/httpd.conf
# forward requests directly to Tomcat's proxy connector running on port 8082
ProxyPass / http://localhost:8082/
ProxyPassReverse / http://localhost:8082/
You will need to restart Apache after making this change.
/etc/init.d/httpd restart
Conclusion
Squid is a very powerful tool for caching. It is not for all applications. Please examine the need of your application and use squid appropriately. I’ve used squid for several years for caching the output from a Java data mashup application and am very satisfied with the ease of use and benefits. Hope you found this tutorial useful. Feel free to post a comment or share your experience with squid.
Docbook is an XML format generally used for writing technical documentation. Many technical projects have documentation written in Docbook XML and checked in the source control system along with the source code. This makes it easy to ship documentation with the source and lets you keep versions of documentation in sync with the product version. This tutorial shows you how to write your first docbook documentation in a Maven project.
Write a simple docbook file
Create the following file:
src/docbkx/test.xml
A minimal docbook file
<?xml version="1.0" encoding="utf-8"?>
<article xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en">
<title>Hello, World</title>
<para>My first documentation with Docbook</para>
</article>
Generate html documentation
Configure pom.xml
The maven docbook plugin converts your docbook xml file to user friendly documentation in HTML. Add the following plugin declaration to your pom.xml
The above config runs the plugin in pre-site phase, and will automatically be called when you run mvn site. You can use the following command to manually run the plugin for purpose of testing:
mvn pre-site
This simple config scans the src/docbkx directory and produces the html documentation in target/docbkx/html directory. You should see the following output file:
target/docbkx/html/test.html
More plugin options
The plugin goal used above generate-html converts the docbook xml to html. There are advanced options to configure the CSS/XSLT used. Also, there are other goals available to generate documentation in more formats including pdf. Here’s the reference page for plugin documentation.
Now that you are able to create a sample docbook and publish it, you might want to learn the Docbook format itself. Here are some links that should help you get started:
Download the schemas for docbook to get validation and auto-completion in your XML editor
Google Buzz is yet another way to share photos, status updates, videos, news and more with friends and family.
Buzz is part of Gmail, so unlike other social networking sites where you have to build your community from scratch, Buzz lets you start from your existing Gmail contacts. If you’re not already on Gmail then it makes it less attractive to try it, in my opinion.
Buzz also shows you activities from Picasa, Google Reader, Flickr and Twitter so you can see all of that in one place.
There is no need to register, download or setup anything. Buzz is automatically available from your Gmail. Just go to your Gmail and you should see a new ‘Buzz’ link under your ‘Inbox’ in the left hand pane. Buzz is being rolled out so if you don’t see the ‘Buzz’ link, you don’t have it yet.
The buzz official website is: http://buzz.google.com. Here’s the official intro video from Google.
This article shows you best practice for serializing Java enums to database (via Hibernate, JPA) or file. It discusses three ways to serialize enums with code examples, the pros and cons of each way and also recommends the best way. You should know this if you are serializing an Object with an enum field to a file or mapping a POJO to a database table using technologies like Hibernate or JPA.
What exactly is a Java enum constant? A Java enum is a sub-class of java.lang.Enum. An enum constant is simply an object instance of the enum class. The enum constructor must be private. Enum constants are created by the JVM via an invocation of the private constructor. Customizing the constructor signature is the most common way of adding more data to the enum class. You can add methods to the enum class just like any other class.
What does serialization and deserialization of enum mean? Serialization involves converting the enum to a value (usually primitive or a String) which can be easily stored on the disk or a database. Deserialization involves reading a stored value and converting it back to an enum. It is important to understand the different ways in which enum serialization and deserialization works. Sometimes ORM implementations (like Hibernate) may automatically do the enum serialization for you, however there are drawbacks to some of these approaches that you should know.
Let’s say we want to serialize the following enum
public enum Color {
RED, GREEN, BLUE;
}
Following are 3 different approaches. The last approach is the most reliable way of serializing an enum class, however you should know approaches 1 and 2 so you can understand their drawbacks.
You can serialize the enum by converting the enum to its ordinal() value.
Color color = Color.GREEN;
int ordinal = color.ordinal(); // ordinal == 1
// save ordinal
At a later point, you can deserialize the saved int using the values() method on the enum which returns all the enum constants in the order in this they were declared.
// retrieve from saved value
Color savedColor = Color.values()[savedOrdinal];
This approach is simple and works. Some ORM implementations may automatically use this approach if you map your enum to and Integer column. However, the biggest drawback of this approach is that if new constants are introduced out of order then the serialized values will not be properly reconstructed.
Here’s the error scenario:
Serialize an enum value Color.GREEN. Saved value gets stored as 1
Developer adds a new color ORANGE between RED and GREEN
The previously serialized value of 1 is now mapped to ORANGE.
Color color = Color.GREEN;
String savedValue = color.name();
// save value
Deserialize as follows:
Color savedColor = Color.valueOf(savedValue);
valueOf() is a built-in method which returns the enum constant with the specified specified name
This method works as well. Some ORM implementations may automatically use this approach if you map your enum to and String (char, varchar) column.The serialized form is String (as opposed to int in the previous example). The main drawback of this approach is that the serialized value, which can then be stored on disk or in database and can be persisted for a long term, is now dependent on a Java constant name. A developer may accidentally rename the constant name without realizing that it will make the previously serialized values unreadable.
Here’s the error scenario:
Serialize an enum value Color.GREEN. Saved value gets stored as “GREEN”
Developer renamed enum constant from Color.GREEN to Color.Green.
The previously serialized value of “GREEN” can no longer be mapped to an existing color.
This approach involves assigning a an explicit user defined value to each enum constant and defining a toValue() and fromValue() methods on the enum to do the serialization and deserialization.
public enum Color {
RED("RED"), GREEN("GREEN"), BLUE("BLUE"), UNKNOWN("UNKNOWN");
private final String value;
Color(String value) {
this.value = value;
}
public static Color fromValue(String value) {
if (value != null) {
for (Color color : values()) {
if (color.value.equals(value)) {
return color;
}
}
}
// you may return a default value
return getDefault();
// or throw an exception
// throw new IllegalArgumentException("Invalid color: " + value);
}
public String toValue() {
return value;
}
public static Color getDefault() {
return UNKNOWN;
}
}
This approach is better than approach 1 and approach 2 above. It neither depends on the order in which the enum constants are declared nor on the constant names.
To serialize:
Color color = Color.GREEN;
String savedValue = color.value();
// save value
To deserialize:
Color savedColor = Color.fromValue(savedValue);
Note: You can choose an Integer instead of String as a value, but remember this value must not change or you will be unable to retrieve you persisted values.
Mapping enum to database column using JPA/Hibernate
You can use any of the 3 approaches discussed above.
Map the enum to an integer column. The persistence implementation should automatically convert enum to ordinal() and back for you.
Map the enum to a String column. The persistence implementation should automatically convert the enum value to String value via the name() function.
Map the enum using a business value. You should mark the enum field as @Transient, and create another String field which you can map to a String column in your database table. Here’s an example code snippet.
@Entity
public class Product {
@Column
private String colorValue;
@Transient
public Color getColor() {
return Color.fromValue(colorValue);
}
public void setColor(Color color) {
this.colorValue = color.toValue();
}
}
Conclusion
We saw 3 different ways to serialized enums in this article. Approach 1 and 2 above use ordinal() and name() respectively, and require no additional work, but are inherently unsafe to use. The safest way is approach 3 which uses a custom user defined value as shown in the example above. When persisting enums with Hibernate/JPA first convert them to a user defined value.
Clickframes is a Code Generation framework written in Java designed specifically to generate (Java) web applications.
Philosophy behind Clickframes
There are 2 aspects to a web application:
What the application does.
How it does it.
The key idea behind Clickframes is separation of these two concerns.
What the application can be defined by focusing on end user experience – what the end user sees, what the user clicks and so on. When users open a webapp in a browser they see a page, links, forms, inputs, content. They don’t see how the page was produced, which technology, framework or database was used on the back end. Defining what an application does boils does to defining a web page, after all a web application is most part is a collection of web pages linked to each other via links and form actions.
On the other hand, how an application is implemented consists of every little detail that happens “behind the scenes”. Which technology, platform and database is used, all the choices which result in a working application – but are never directly seen by the end user directly.
Clickframes separates these two aspects of the application by defining an application model called Appspec. Appspec is a rich data structure which represents the application behavior. The business analyst defines the application behavior using the Appspec model. The developer writes code generators to implement a generic Appspec and then runs them for the specific Appspec written by the business analyst. Appspec becomes a contract and a way of communication between the analyst and the developer. In the meantime QA takes the Appspec and writes tests against it. Appspec becomes a way of communication and the single source of truth for the various members of the team.
To give you a concrete sense of what I am talking about, let’s say that the Appspec has a page called “home”. The developer may choose to implement this using a simple jsp file “home.jsp”. The developer then generalizes this implementation and creates a code generator to produce a file called [page id].jsp for every page in the Appspec. Again, the philosophy being “if I can figure out how to implement one page, I can apply the same approach for all pages”. This approach implemented via a set of code generators applied against the application definition (or Appspec) is the key idea of the Clickframes approach. The result is an automatically generated application for a given target platform/technology (e.g. “jsp” in the previous example) which produces consistent code for the entire application. This code is produced using code generators at minute zero of your project, i.e. even before you start working on your project. You can then take the generated code and start customizing it. This is a great productivity boost as you can use the same code generators from one project to another as they are not specific to any particular application, but are written for the generic Appspec model for the given target technology/platform. Such code generators usually exists are code generation templates and are referred to as Clickframes Plugin.
Terminology
To recap the terminology:
Appspec (Application Specification) – Appspec is what the web application does, from an end user’s perspective. It essentially captures the behavior of the application. How many pages does the application have, how many forms does each page have. How many input fields on each page. What type of input fields (e.g. text, textarea, radio, dropdown). Are there any validation rules on the input fields (e.g. must be 8-12 characters, or must be a zipcode, must be a valid email format). What is the next page when the user submits a form on a page. How many links on the page, do the links point to another page in the application or an external link. The list goes on, but you get the idea.
Clickframes Plugin – Clickframes Plugin is a code generator, usually implemented by creating a set of templates, which inputs an Appspec and generates code. A plugin is usually a zip file consisting of dozens of templates written in plain text or velocity. Plugins can also be written or extended in Java using the Clickframes Plugin API.
Clickframes Plugin Authors – (Usually) Senior or Experienced developers who have a good understanding of the target technology create a plugin to implement the Appspec. Note that this activity needs to be done only once per technology. For example, once I have created a Seam2 plugin, you can generate any number of applications by simply writing an Appspec for your application and generate Seam code by using the plugin.
Target language/platform – Clickframes is a Code Generation framework that you use before you even start your project. It generates code that you then compile and run. Target platform refers to the platform on which the generate code runs. Example target platforms are Java/Tomcat, Java/Seam/JBoss, JSF/Tomcat, PHP. If you are willing to write your own code generation templates, you can generate code for any language/target platform.
Why Clickframes?
One advantage of Clickframes is that it acts as a medium of communication between the various members of the team.
However, the most powerful feature of Clickframes is the Clickframes Code Generation Plugins. Once you write a plugin for a technology or platform, you can instantly generate a full working application by simply writing the Appspec for that application and running the Clickframes Plugin on this Appspec . Writing an Appspec should be much easier than implementing the application itself.
Hello, World example
Let say an application has one page which has the text “Hello, World”. You can create the Appspec by either using the Java API or XML format.
Appspec appspec = new Appspec();
Page home = new Page();
Content message1 = new Content();
message1.setId("message1");
message1.setText("Hello, World");
home.getContents().add(message1);
appspec.getPages().addPage(home);
Clickframes sample JSP Plugin
Now lets build a simple JSP code generator. This code generator is just for the purpose of illustration and is not intended to be a real production quality plugin.
Create a file called ${page.id}.jsp. Since the file name consists of the variable ${page} this file will automatically be applied to all pages in the application.
Contents of ${page.id}.jsp below. All templates are written in Apache Velocity.
The ${page} variable passed to the template represents the Java object defined above.
You can now add a dozen pages to your application and reuse the same code generation template.
A more comprehensive demo
The above example is good to give you a quick sense of how the code generation works. However, real applications contains forms, links, inputs, actions, entities, databases and so on. The following example uses a JSF Seam2 plugin which is used to generate a simple Issue Tracker Application.
The best way to jump in and get your feet wet is by seeing and running the code. I have created a JSF Seam2 plugin which generates JSF2 and Seam based web applications.
cd clickframes-seam-issuetracker-demo
mvn glassfish:run
See the application run at: http://localhost:8080/issuetracker/
You can type any login/password to login. The login module implemented by default does passes any input. In the future I plan modify the plugin to properly implement login.
Key demo features:
Security: pages with login-required=”true” will automatically prompt you for login.
AJAX input validation: inputs with validation will prompt you with an error as you type if the validation fails
Built-in CRUD implementation using in-memory database: actions marked with “update” or “create” will actually create an entity and store it in an in memory database
Note that this application is 100% generated directly from the Appspec. What is means is that you can modify the application behavior by modifying the Appspec and regenerate the application.
Regenerate:
mvn clickframes:generate
Can you really model every single thing about a web application?
No. Clickframes focuses on things which can be easily modeled. Even if you are able to capture 50% of the application features in the Appspec, you can generate a working application which implements 50% of requirement without writing a single line of code. That’s quite a jump in productivity. You can then hand code the remaining application the usual way.
Case for Clickframes
Clickframes is not for all web applications. If the Clickframes model fits your application model then I urge you to give Clickframes a try. With Clickframes you can produce consistent code for your entire application. You can bake the best practices right into the code generation templates. Moreover, you can use these templates from one project to another.
Maven Central Repo is the official Maven repository where all “official” jars are published. It is also known as the “central” repo and is part of the super pom.xml which is implicitly included by every Maven project. The URL of the Maven Central Repo is http://repo1.maven.org/maven2/.
If you need to share your Maven artifacts with the world, you too can publish it on the official Maven repo! Let others discover your artifacts without any repository configuration. This article is intended to be a practical, step by step, easy to follow tutorial to publish your artifacts to the central repo.
Step 1: pom.xml configuration
Required elements: These elements must be present in your pom.xml: modelVersion, groupId, artifactId, packaging, name, version, description, url, licenses, scm url, dependencies
No <repositories> or <pluginRepositories> tag allowed. All you dependencies must be present in the central repo.
Choose a groupId that you own. Most common way to do this is to have control over the domain name corresponding to your groupId. For example, if your groupId is com.vineetmanohar then your must own or have control over the domain name vineetmanohar.com. This is required as maven will only download artifacts for a groupId from the corresponding domain.
You can only publish releases, not snapshots.
Step 2: Create your domain repo
This assumes that you have a hosted server somewhere which runs apache (or similar web server to host static files), and describes how to create a repo using by defining an path in a apache virtual server. If you have root access to the machine, Login as root and create a new user called ‘repo’
# adduser repo
# su - repo
As the repo user and create the repo directories.
# su - repo
$ cd /home/repo
$ chmod 755 .
$ mkdir -p html/releases html/snapshots
Now map this directory to apache
Map /home/repo/html/ to http://repo.<your domain>.com
Edit the /etc/httpd/conf/httpd.conf file and add the following mapping. Change IP address and server name as applicable. Remember that server name must match or should be a sub-domain of your groupId.
Once you are ready to release, change your pom.xml version to a non-SNAPSHOT version, e.g. 0.0.1. Remember that if your version is a non-SNAPSHOT version, you cannot have any SNAPSHOT dependencies either, that’s just a universal maven rule.
Now deploy your version to your release repo.
mvn deploy
If you use scp to deploy (as in the example above) you will be asked to enter your password. Alternatively you can configure to SSH without password.
PS: Alternatively you can automatically increment version and deploy automatically by using the Maven Release plugin.
Step 4: Give permission to Maven to access your repo
The simplest way is to authorize Maven by adding its private key to your repo’s authorized ssh keys. Make sure that the permissions are set as described below.
# su - repo
$ mkdir -p .ssh
$ chmod 700 .ssh
$ cd .ssh
$ vi authorized_keys
<paste maven's public key in file authorized keys>
$ chmod 400 authorized_keys
Copy the contents of Maven’s public key and paste it in /home/repo/.ssh/authorized_keys
Step 5: Submit a request to the Maven folks
You have your artifacts published in a public repo and Maven has the permission to rsync your repo over SSH. All you need to do now is to submit a request to Maven to add your server to the list of servers they sync with.
Open an account at http://jira.codehaus.org, if you don’t have one already. Once you have created an account, submit your request here.
Here is an example request that I submitted. It took them 7 days to close the ticket, so be patient. After the ticket has been closed, it might take half a day for the servers to gets sync’d, after which I could see my artifacts appear here.
The file “hello.txt” shows up in directory listing via the “ls” command. The puzzler is about trying to display the contents on the file via the “cat” command.
Following is a real transcript demonstrating the puzzler.
$ whoami
vineet
$ ls -al
total 12
drwxr-xr-x 2 vineet vineet 4096 Nov 15 11:15 .
drwx------ 15 vineet vineet 4096 Nov 15 11:14 ..
-rw-r--r-- 1 vineet vineet 42 Nov 15 11:14 hello.txt
$ cat hello.txt
cat: hello.txt: No such file or directory
Puzzler: Why can’t we display the contents of the file “hello.txt”?
Maven Twitter Plugin lets you send Twitter status updates from Maven, without writing any Java code. It increases communication between Project owners and Project users by automatically tweeting build and release status via Twitter.
Configuration
1. Add Plugin repository to your <build> <plugins> section in pom.xml
You need to add this to your list of existing plugin repositories.
Now add one <execution> block to the above, for every Tweet you want to send per build. The <twitterStatus> config element defines your Twitter message and will be executed in the phase specified by the <phase> subelement.
This example send 2 tweets: one in the “test” phase and the other in the “deploy” phase.
<plugin>
<groupId>com.vineetmanohar</groupId>
<artifactId>maven-twitter-plugin</artifactId>
<version>0.1</version>
<executions>
<!-- phase: test -->
<execution>
<id>test-passed</id>
<configuration>
<!-- anything you want, upto 140 chars -->
<twitterStatus>My first tweet from using #maven twitter plugin</twitterStatus>
</configuration>
<phase>test</phase>
<goals>
<goal>tweet</goal>
</goals>
</execution>
<!-- phase: deploy -->
<execution>
<configuration>
<!-- Tell your users that the project is deployed -->
<twitterStatus>Version ${project.versionId} of XYZ deployed</twitterStatus>
</configuration>
<id>deploy</id>
<phase>deploy</phase>
<goals>
<goal>tweet</goal>
</goals>
</execution>
</executions>
</plugin>
FAQ
What can I put under the <twitterStatus> element
static text
You can be creative and put variables related to your project. ${project} maps to the Maven Project Model. Examples are ${project.groupId}, ${project.artifactId}, etc
You can put hash tags by simply putting # before a word
You can put @usernames directing the message to a specific twitter account
You resolved twitter message, after resolving any ${vars}, should be maximum 140 chars
What happens if I send multiple message with the same text
Twitter seems to ignore status updates if there is not status change from your.
What happens if my <twitterStatus> is more than 140 characters
The current version does not check for length and will send your message to Twitter. Twitter will respond with an error.
Does this plugin support URL shortening?
Version 0.1 does not support URL shortening.
Does maven execution stop if the Twitter Plugin fails
No. All errors are logged, but no Exception is thrown.
Is there a limit to how many messages I can send?
Yes. Twitter has a rate limit of 150 message per hour. See details.
Yahoo! Grid CSS system is an easy way to create an HTML document with a desired page width and a secondary column which works out of the box. YUI Grid comes with four built-in page widths and six built-in template presets. This article shows you how to create a custom page width and a custom secondary column width.
Yahoo! Grid Page structure
The overall structure of a HTML document using yahoo grid is as follows:
You can control the overall width of the page using the id of the outermost div (<div id=”doc”, in the above example). There are 4 pre-defined doc ids:
doc: 750px
doc2: 950px
doc3: 100%
doc4: 974px
Customizing the Page Width
To create your custom page width, say 800px, add the following in your CSS
#doc20 {
width:61.538em; /* 800/13 */
*width:60em; /* for I.E. 800/13.3333 */
}
You can add a secondary column by simply nesting 2 blocks, <div class=”yui-b”>, under “bd”. You need to indicate which block is the main block by wrapping it in <div id=”yui-main”>.
Maven exec plugin lets you run the main method of a Java class in your project, with the project dependencies automatically included in the classpath. This article show you 3 ways of using the maven exec plugin to run java, with code examples.
1) Running from Command line
Since you are not running your code in a maven phase, you first need to compile the code. Remember exec:java does not automatically compile your code, you need to do that first.
mvn compile
Once your code is compiled, the following command runs your class
Defines the scope of the classpath passed to the plugin. Set to
compile, test, runtime or system depending on your needs
cleanupDaemonThreads (exec.cleanupDaemonThreads)
Wether to interrupt/join and possibly stop the daemon threads upon
quitting. If this is false, maven does nothing about the daemon threads.
When maven has no more work to do, the VM will normally terminate any
remaining daemon threads.
In certain cases (in particular if maven is embedded), you might need to
keep this enabled to make sure threads are properly cleaned up to ensure
they don't interfere with subsequent activity. In that case, see
daemonThreadJoinTimeout and stopUnresponsiveDaemonThreads for further
tuning.
This defines the number of milliseconds to wait for daemon threads to quit
following their interruption. This is only taken into account if
cleanupDaemonThreads is true. A value <=0 means to not timeout (i.e. wait
indefinitely for threads to finish). Following a timeout, a warning will
be logged. Note: properly coded threads should terminate upon interruption
but some threads may prove problematic: as the VM does interrupt daemon
threads, some code may not have been written to handle interruption
properly. For example java.util.Timer is known to not handle interruptions
in JDK <= 1.6. So it is not possible for us to infinitely wait by default
otherwise maven could hang. A sensible default value has been chosen, but
this default value may change in the future based on user feedback.
executableDependency
If provided the ExecutableDependency identifies which of the plugin
dependencies contains the executable class. This will have the affect of
only including plugin dependencies required by the identified
ExecutableDependency.
If includeProjectDependencies is set to true, all of the project
dependencies will be included on the executable's classpath. Whether a
particular project dependency is a dependency of the identified
ExecutableDependency will be irrelevant to its inclusion in the classpath.
Indicates if this plugin's dependencies should be used when executing the
main class. This is useful when project dependencies are not appropriate. Using
only the plugin dependencies can be particularly useful when the project is not
a java project. For example a mvn project using the csharp plugins only expects
to see dotnet libraries as dependencies.
Wether to call Thread.stop() following a timing out of waiting for an
interrupted thread to finish. This is only taken into account if
cleanupDaemonThreads is true and the daemonThreadJoinTimeout threshold has
been reached for an uncooperative thread. If this is false, or if
Thread.stop() fails to get the thread to stop, then a warning is logged
and Maven will continue on while the affected threads (and related objects
in memory) linger on. Consider setting this to true if you are invoking
problematic code that you can't fix. An example is Timer which doesn't
respond to interruption. To have Timer fixed, vote for this bug.
systemProperties
A list of system properties to be passed. Note: as the execution is not
forked, some system properties required by the JVM cannot be passed here.
Use MAVEN_OPTS or the exec:exec instead. See the user guide for more
information.
testSourceRoot (testSourceRoot)
This folder is added to the list of those folders containing source to be
compiled for testing. Use this if your plugin generates test source code.
FAQ and Errors
Why do I get this error when specifying arguments to my main method:
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Failed to configure plugin parameters for: org.codehaus.mojo:exec-maven-plugin:1.1.1
on the command line, specify: '-Dexec.arguments=VALUE'
Cause: Cannot assign configuration entry 'arguments' to 'class [Ljava.lang.String;' from '${exec.arguments}',
which is of type class java.lang.String
[INFO] ------------------------------------------------------------------------
[INFO] Trace
org.apache.maven.lifecycle.LifecycleExecutionException: Error configuring: org.codehaus.mojo:exec-maven-plugin.
Reason: Unable to parse the created DOM for plugin configuration
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:588)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:513)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:483)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:331)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:292)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:142)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:336)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:129)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:301)
Solution
exec.arguments was used before version 1.1 of the exec plugin, it did not support conversion of command line String to String[] array.
If possible upgrade to 1.1 or later and use exec.args instead of exec.arguments.
If you can't upgrade the plugin version, you can still use command line arguments with a profile and use multiple <argument> tags associated in the pom.xml
Most Popular