Friday, June 8, 2007

Build Struts 2 Application Using Maven 2

I really think that using Maven as tool to build Java Projects is simply great, but if there is one thing I hate is searching ibiblio for the dependencies I need for my project. So I will post below the path for the main components one will need to get started with Struts 2 on his project.

By default, Maven will look for the dependencies on its central repository http://repo1.maven.org/maven2. It is possible to configure the repositories where you want maven to look up for files. These two below are some alternative repositories where you can try to find components you need. In the apache repository below is possible to find the SNAPSHOT version of the components.

Just add the code below into your pom file.


<repositories>
  <repository>
    <id>ibiblio</id>
    <name>iBiblio Maven2 Repository</name>
    <url>http://www.ibiblio.org/maven2</url>
  </repository>
  <repository>
    <id>apache-repo</id>
    <name>Apache Repository</name>
    <url>http://people.apache.org/repo/m2-snapshot-repository</url>
  </repository>
</repositories>


Check the official Maven site about how to setup multiple repositories.

Now, we can reach for those components! :)
As advised by the struts team, the minimum set of components one might need is below.

  • struts2-core.jar

  • xwork.jar

  • ognl.jar

  • freemarker.jar

  • commons-logging.jar


Fortunately, to download all of them automagically, all you need to add to your pom files are the lines below:


  <dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-core</artifactId>
    <version>2.0.6</version>
  </dependency>


Wanna do this even faster? Use maven archetypes to create a struts2-aware project! ;)


mvn archetype:create -DgroupId=tutorial \
    -DartifactId=tutorial \
    -DarchetypeGroupId=org.apache.struts \
    -DarchetypeArtifactId=struts2-archetype-starter \
    -DarchetypeVersion=2.0.5-SNAPSHOT \
    -DremoteRepositories=http://people.apache.org/repo/m2-snapshot-repository

Monday, April 23, 2007

Quiclky Create a Maven-aware project

If you are (or want to start) using Maven as a build tool for your project, a quick way to start is to use an archetype to create a pom.xml and the default folder structure. This is the command:


mvn archetype:create

-DarchetypeGroupId=[archetype-groupId]

-DarchetypeArtifactId=[archetype-artifactId]

-DarchetypeVersion=[archetype-version]

-DgroupId=[my.groupid]

-DartifactId=[my-artifactId]

Friday, April 13, 2007

Debugging Information passed to a JSP Page

Well, scriptlets inside a JSP page Suck. Alright, I agree!!
But sometimes it is necessary to check what are the parameters in the request or session scopes reaching your jsp page.

I found this code somewhere on the web sometime ago. One day (yeah, right) I will right a version of it using JSTL tags, but for now I allow myself to add this scriptlet in one of the pages that are included everywhere in my system. As I use Struts Tiles in my system, I do have a bottom.jsp page which is included everywhere.

So I leave the debug attribute in false state until I need to debug on page or another. At this moment, all I have to do is turn on the debug information in my page by setting the attribute to true.

Below is the scriptlet and page includes that should be added to the page where you want the debug information to be displayed.


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ page import="java.util.*" %>
<%@ page import="org.apache.struts.*" %>

<%@ page import="org.apache.struts.util.*" %>
<%@ page import="org.apache.struts.action.*" %>

<%
// Print all attributes in the request object
out.println("<p><b>All Attributes in request scope:</b>");
Enumeration paramNames = request.getAttributeNames();
while (paramNames.hasMoreElements()) {
String name = (String) paramNames.nextElement();
Object values = request.getAttribute(name);
out.println("<br> " + name + ":" + values);
}

// Print all attributes in the session object
out.println("<p><b>All Attributes in session scope:</b>");
paramNames = session.getAttributeNames();
while (paramNames.hasMoreElements()) {
String name = (String) paramNames.nextElement();
Object values = session.getAttribute(name);
out.println("<br> " + name + ":" + values);
}

out.println("<p><b>Data in ActionMessages:</b>");

// Get the ActionMessages
Object o = request.getAttribute(Globals.MESSAGE_KEY);
if (o != null) {
ActionMessages ae = (ActionMessages)o;

// Get the locale and message resources bundle
Locale locale =
(Locale)session.getAttribute(Globals.LOCALE_KEY);
MessageResources messages =
(MessageResources)request.getAttribute
(Globals.MESSAGES_KEY);

// Loop thru all the labels in the ActionMessage's
for (Iterator i = ae.properties(); i.hasNext();) {
String property = (String)i.next();
out.println("<br>property " + property + ": ");

// Get all messages for this label
for (Iterator it = ae.get(property); it.hasNext();) {
ActionMessage a = (ActionMessage)it.next();
String key = a.getKey();
Object[] values = a.getValues();
out.println(" [key=" + key +
", message=" +
messages.getMessage(locale,key,values) +
"]");
}
}
}
%>


Tuesday, April 10, 2007

EJB3 QL: Using the COUNT function

If you are using EJB3 Query Language to build your application, you will probably need to use some functions other than the regular SELECT statements and logical WHERE clauses. One of the most simplest of these functions is the COUNT function.
The syntax for the COUNT function is very simple, and it receives only a parameter which is the identifier to be count, as in:

SELECT COUNT(c) FROM Customers AS c WHERE c.address.country = 'BR'


This query will count all the Customers who live in Brazil.

The COUNT function can be used with an identifier, in which case it always counts entities (as the example above demonstrates), or with path expressions but this last one can always be converted into an expression that counts entities only by managing the conditions in the WHERE clause.

Below is an example on how you could write a piece of code that would count the Patients from a medical database, depending on which Clinic they are registered to:


Query query = entityManager.createQuery("SELECT COUNT (p) FROM Patients p WHERE p.clinic.idtClinic = :idtClinic");
query.setParameter("idtClinic", idtClinic);
return (Long)query.getSingleResult();


I will write about other EJB QL functions later! :)

CU!

Sunday, March 11, 2007

SVN Keywords

One useful feature that subversion and many other Versioning Systems offer for developers is the ability to include keywords in text files stored in the repository.

These keywords get replaced when some action is done on them by the server. This book excerpt (reproduced below) documents some keyword supported by subversion.

The keyword to be replaced is identified by an anchor in the text with the keyword name surrounded by two '$keywordName$.

Subversion defines the list of keywords available for substitution. That list contains the following five keywords, some of which have shorter aliases that you can also use:

LastChangedDate

This keyword describes the last time the file was known to have been changed in the repository, and looks something like $LastChangedDate: 2002-07-22 21:42:37 -0700 (Mon, 22 Jul 2002) $. It may be abbreviated as Date.

LastChangedRevision

This keyword describes the last known revision in which this file changed in the repository, and looks something like $LastChangedRevision: 144 $. It may be abbreviated as Revision or Rev.

LastChangedBy

This keyword describes the last known user to change this file in the repository, and looks something like $LastChangedBy: harry $. It may be abbreviated as Author.

HeadURL

This keyword describes the full URL to the latest version of the file in the repository, and looks something like $HeadURL: http://svn.collab.net/repos/trunk/README $. It may be abbreviated as URL.

Id

This keyword is a compressed combination of the other keywords. Its substitution looks something like $Id: calc.c 148 2002-07-28 21:30:43Z sally $, and is interpreted to mean that the file calc.c was last changed in revision 148 on the evening of July 28, 2002 by the user sally.
as in $keywordName$.

Have fun!

UPDATE on march/2009
Normally it would be necessary to set the properties on every single file of your system so the replacement of these props would happen. However, there is an easier way to do this, which is set the auto-props property in your environment.

In folder "C:\Documents and Settings\[your_username]\Application Data\Subversion" you will find a file named config (with no extension). In this file there should be a property "enable-auto-props" commented out. Remove the comment from this line so it looks like this:


### Set enable-auto-props to 'yes' to enable automatic properties
### for 'svn add' and 'svn import', it defaults to 'no'.
### Automatic properties are defined in the section 'auto-props'.
enable-auto-props = yes

Then, on the same file, find the section [auto-props] and add a line at the end. If you want the replacement to happen only in your java files, add this:


*.java = svn:keywords LastChangedDate

Monday, February 26, 2007

Install a jar file into maven's local repository

Sometimes, while using maven to build your projects, it is necessary to add a needed jar file directly into your local repository. This should not be a need if you have a remote repository correctly setup, but it might be useful if it is a too bureaucratic task or any other reason.

It is as simple as this. Having the file to be installed in your local repository in the local folder, issue the command below to install it.

mvn install:install-file -DgroupId=<MVN_GROUPID> -DartifactId=<MVN_ARTIFACTID> -Dversion=<MVN_VERSION> -Dpackaging=jar -Dfile=<JAR_FILE_TO_INSTALL>

Could be useful! ;)

Sunday, February 11, 2007

Find the name of your session bean in JBoss

If you are writing JEE applications, you will most likely write a Session Bean to provide your View Tier with the services it need. This Session Bean is reached by the client application through a service called JNDI.

The problem is that each Application Server uses a different JNDI provider and this makes portability very hard to achieve. I wrote the code below to allow me to access the JNDI service and find my Session Bean. Please note that this would be much better placed in the container configuration file and not in the code, as it is here.

protected static Context getInitialContext( ) throws javax.naming.NamingException {
  Properties p = new Properties( );
  p.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
  p.put(Context.URL_PKG_PREFIXES,"org.jboss.naming:org.jnp.interfaces");
  p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
  return new javax.naming.InitialContext(p);
}

This method will return a java.naming.Context object which can be used for the lookup on the service, like this:


PatientServices patientServices = (PatientServices)jndiContext.lookup("PatientBean/remote");



And how can you find the name under which your bean has been published on the application server? Well, in JBoss all you need to do is access the jmx-console (default URL is http://localhost:8080/jmx-console/). On the jboss session from this page, find the JNDIView service. Click on it and a new page will display on your browser.
On this new page there will be a java.lang.String list() MBean operation, and clicking on the invoke button the names of all available JNDI names will be shown on a tree-like structure which composes the name under which your Session Bean is registered on the JNDI service.