Archive

Archive for the ‘Solutions Log’ Category

Getting Started With Git and GitHub

April 22nd, 2012 No comments

For the last two years, I have been using Git on a windows machine. Recently, I had to install Git on my Mac and connect to Github. Since I have not blogged for such a long time, I thought of jotting down my notes here.

Setting Up Git Locally

1. The first step in this process is to download and install Git locally. The easiest way to do is to download the Git OS X installer from http://code.google.com/p/git-osx-installer/downloads/list The recent version at the time of writing is 1.7.9.4.

Once the download is complete, just run the installer. Upon successful installation, run the following command:

2. The next step is to configure Git. To do this, run the following commands from the command line:

git config –global user.name “YOUR_NAME”
git config –global user.email “YOUR_EMAIL”

3. Now we are ready to create a Git repository. To do that, create a new directory where you want to store your project files. For this blog, I have created a new folder called “hellogit” and moved to the folder in the terminal.

To create a new repository, simply run the following command in the project folder:

4. Now we are ready to add files to our repository. Assume that we have two files in our project test.html and test2.html. Move the files into the hellogit project folder.

Now run the git status command to know the latest status of our repository:

Git comes back saying that we have two untracked files. Git does not automatically track the files in our repository. Instead we need to explicitly add them.

5. To add files to Git, simply run the following command:

If you are new to Git, you might be wondering about the lack of feedback from Git about the add command. Just remember that upon a successful command execution, Git typically does not give you any feedback.

Let’s run the status command to see what happened:

From the above image, you can see that Git added our two files. It also mentions that we have a OS specific file DS_Store that needs to be tracked. We will address that in a minute.

6. When we are done making changes to our project files, we can check them in. To do that, simply run the following command:

In the above command, I have given a commit message “Initial Commit”.

7. Often we will end up with project and OS specific files (DS_Store) in our project folder that we don’t want to check in to Git. We can tell Git to ignore certain files and never track them. To do that, we simply create a .gitignore file that has the name(s) of the file that needs to be ignored.

Now, when the .gitignore file is in place, run the status command and you will see that the .DS_Store file is no longer tracked.

Preparing For Github

Before you can start using Github remote repository, you need to setup SSH keys. These keys are needed to establish secure connection between your computer and Github. To do that follow these steps:
1. Run the following command:

The No such file or directory indicates that you don’t have any SSH keys. Sometimes, the folder might exist but it might not have the id_rsa* SSH key files.

2. The next step is to create a new SSH key. Run the following command:

Hit enter to accept the default location. You will be asked to enter a passphrase. Enter a pass phrase and make a note of it as we will need it again.

Connecting To Github

1. Before we can push our code to a github repository, we need to create an account. Go to http://github.com and create a new account.

2. Once you have created and logged into your account, you need to give github your SSH key. In order to do that, go to your account settings page and click the SSH Keys Navigation Item:

3. Copy the SSH key you created above. To do that, simply go to the .ssh folder and type the following command:

4. Click the Add SSH Key button and enter the key as well as a title.

5. Go back to the terminal and try to connect to github using this command:

When you accept Yes, you will be asked to enter the passphrase:

Check the “Remember Password in keychain” and hit Ok.

6. Now, we are ready to start pushing code to Github. Before we do that we need to create a remote repository on Github. To do that, click the New Repository button:

Enter the following information for the new repository:

Make sure you leave all the fields in their default state.

7. Once the repository has been created on Github, move to your terminal and cd.. into the hellogit project. Then run the following two commands (replace bava with your username):

Now, go back to your Github repository https://github.com/YOUR_USER_NAME/hellogit and you will see that the files have been pushed.

Categories: Git, Solutions Log Tags: ,

SiteMesh And Script Tag

July 29th, 2010 No comments

In a Sitemesh application I recently had to read code inside <script> tags of the decorated pages and use it in the decorator page. After little research, I found this solution. Based on this, I extended the HTMLPageParser and created a ScriptExtractionRule. The ScriptExtractionRule extends the BlockExtractingRule and retrives the content inside script tag.

However with Sitemesh 2.4.1, this solution did not work for the script tag. When I replaced script with any other HTML tag such as form, I was able to read the content inside that tag. Eventually I ended up putting the JavaScript inside a content tag. Here is a portion of the decorated page.

<content tag=”script”>
function somejsfunction() {
}
</content>

Now in the decorator page, I used the tag to read the JavaScript. Hopefully this helps others struggling with similar issue.

Categories: SiteMesh, Solutions Log Tags:

Maven Multi Module Versioning

April 28th, 2010 6 comments

Recently I have been working on a Maven multi module project with ear, war and ejb artifacts. It has been a pleasant experience till I got to versioning my modules. Consider a multi module project with the following structure:

parent-project
|
|- child-moudle
| |
| |–pom.xml
|
|- pom.xml

The parent project pom.xml holds the version information of the parent project:

com.inflinx
project-parent
1.0.0-SNAPSHOT
pom

Now the child module pom contains a reference to the parent information:


	com.inflinx
	project-parent
	1.0.0-SNAPSHOT


4.0.0
com.inflinx
child-module
jar

Now this is where the problem starts. Since all the child modules need to have an explicit reference to the parent pom version, when it is time to do a release, we have to change the version in parent pom and all the child module poms. This can be a real pain and is very error prone. With a little help from Google, here is what I found:

  1. Ceki on his blog suggested using a property in the parent pom to control the version numbering.
  2. Several maven users would like “automatic parent versioning” according this improvement
  3. Use maven release plugin which would automate the process of changing version numbers across the project

Option three seems to be the correct approach to solve this problem here. But I have heard horrible things about the release plugin and how fragile it is. I will be giving it a try soon. I still think that Maven should support automatic parent versioning as an option for users who don’t (or cannot) get to use the release plugin.

Categories: Maven, Solutions Log Tags: ,

EJB 3 Message Driven Beans in WebLogic 10.3

March 21st, 2010 2 comments

In this post, I will show how to create and test Message Driven Beans in WebLogic 10.3. Here are the steps:

Step 1: The first step is to create projects to hold Message Driven Beans. Using Eclipse IDE, here are the generated EAR and EJB projects:

MDB Project Layout

MDB Project Layout

EAR is the standard packaging mechanism for Java enterprise applications.

Step 2: The next step is to create the Message Driven Bean. The MDB created in this post will be consuming messages from a Distributed Queue with the JNDI name jndi.blogQueue. Refer to the “Distributed JMS Queue on WebLogic 10” post for details on creating Distributed Queues in WebLogic.

	package com.inflinx.blog.springmdb;

	import javax.ejb.ActivationConfigProperty;
	import javax.ejb.MessageDriven;
	import javax.jms.Message;
	import javax.jms.MessageListener;

	@MessageDriven(
			mappedName = "jndi.blogQueue",
			activationConfig = { @ActivationConfigProperty(
					propertyName = "destinationType", propertyValue = "javax.jms.Queue"
				)}
			)

	public class TestMdb implements MessageListener 
	{
	    public void onMessage(Message message) 
	    {
		System.out.println("Received Message: " + message);
	    }
	}

Step 3: The next step is to package the newly created MDB into an EJB which then gets packaged into a ear file for deployment. During development in Eclipse, simply right click on the mdb-ear and click Run -> Run On Server. This IDE deployment assumes that the Oracle Server Adapter is installed in Eclipse and configured to talk to a WebLogic 10.3 server instance.

Step 4: To make sure that the MDB is deployed properly, let us create a MessageGenerator class that adds a message to the queue:

 
		
	public class MessageGenerator 
	{
		public static void main(String[] args) throws Exception
		{
			Context context = getInitialContext();
			
			ConnectionFactory connectionFactory = (ConnectionFactory)context.lookup("jndi.blogfactory");
			Queue queue = (Queue) context.lookup("jndi.blogQueue");
			Connection connection = connectionFactory.createConnection();
			Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			
			MessageProducer producer = session.createProducer(queue);
	
			TextMessage message = session.createTextMessage();
			message.setText("Hello World");
			producer.send(message);
			
			connection.close();
		}
		
		private static Context getInitialContext() throws Exception
		{
			Hashtable env = new Hashtable();
			env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
			// TODO: Change the server and port name to suit your environment before running the class
			env.put(Context.PROVIDER_URL, "t3://localhost:9001");
			return new InitialContext(env);
		}
	}

Running the above class will add a new TextMessage to the Queue. Once a new message is available, the TestMDB’s onMessage() method gets invoked and you should see the message “Received Message: TextMessage[ID:, null]” in the WebLogic console logs.

For the above class to run from Eclipse, make sure that you remove “WebLogic System Libraries” and add weblogic.jar to the MessageGenerator “Run Configurations…”.

Message Generator Run Configuration

Message Generator Run Configuration

Otherwise you will end up getting the error:

Exception in thread “main” java.lang.NoClassDefFoundError: weblogic/kernel/KernelStatus
at weblogic.jndi.Environment.(Environment.java:78)
at weblogic.jndi.WLInitialContextFactory.getInitialContext(WLInitialContextFactory.java:117)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.InitialContext.(InitialContext.java:197)
at com.inflinx.blog.test.MessageGenerator.getInitialContext(MessageGenerator.java:40)
at com.inflinx.blog.test.MessageGenerator.main(MessageGenerator.java:18)

 

Download the source code for this post here.

Optional Packages in Weblogic 10.3

March 18th, 2010 3 comments

Optional Packages provide a great way to share individual jar files among multiple applications. Reusable java classes and third party framework classes are good candidates for deploying as optional packages. In this post I will show how to install and use Optional Packages in Weblogic 10.3.

I. Create Jar file
The first step in the process is to bundle a reusable Java class as a Jar file. To keep things simple, I will create a simple String Utility class.

 	
	public class StringUtil
	{
		public static boolean isEmpty(String text)
		{
			return null == text || "".equals(text);
		}
		
	}

The next step is to create a MANIFEST.MF file with the following information:

Manifest-Version: 1.0
Extension-Name: StringLib
Specification-Version: 1.0.0.0
Implementation-Version: 1.0.0.0

As you can see, the MANIFEST.MF file holds the information about the library such as name and version. The next step is to package the application into a jar file.

 

II. Install Optional Packages
Launch WebLogic console and click on Deployments:

Domain Structure

Domain Structure

Click on Install and on the next screen, browse to the folder containing the jar and select the jar:

Select Jar

Select Jar

Select the defaults on the next page and hit Finish. Restart the server for the changes to take effect.

 

III. Using Optional Packages in Web Application
Open the application’s MANIFEST.MF under META-INF folder and add the following entries:

Manifest-Version: 1.0
Extension-List: strlib
strlib-Extension-Name: StringLib
strlib-Specification-Version: 1.0.0.0
strlib-Implementation-Version: 1.0.0.0

Modify application’s code to start using the StringLib library. Even though Optional Packages are not deployed along with the application, you still might need them in your application’s class path during development. Maven users can do this by changing the jar dependency to provided in their pom.xml file.

 

Download stringlib.jar and demo war file along with source code here.

Categories: Solutions Log Tags:

JSR 303 Bean Validation Using Spring 3

March 10th, 2010 27 comments

The JSR 303 specification provides a metadata model for JavaBean validation. The validation API provides a variety of annotations that makes validation easy at any layer. In this post I will demo Spring 3’s support for JSR 303 in the web layer. You can download the code here (eclipse project).

The first part of the post talks about creating a simple bookstore admin application using Spring MVC. The second part of the post will add JSR 303 validation. If you are an experienced Spring developer, you can safely skip to the second part. The final part will show how to customize the validation error messages.

1. Online Bookstore Admin Application

The admin application will be designed to allow administrators enter information about new books. Here are the steps that implement this requirement:

Step 1. Create a web project and add all the required jars
I will be using Eclipse’s and here is a list of the required jars that need to be in the classpath:

org.springframework.asm-3.0.1.RELEASE.jar
org.springframework.beans-3.0.1.RELEASE.jar
org.springframework.context-3.0.1.RELEASE.jar
org.springframework.context.support-3.0.1.RELEASE.jar
org.springframework.core-3.0.1.RELEASE.jar
org.springframework.expression-3.0.1.RELEASE.jar
org.springframework.test-3.0.1.RELEASE.jar
org.springframework.web-3.0.1.RELEASE.jar
org.springframework.web.servlet-3.0.1.RELEASE.jar
commons-collections-3.1.jar
hibernate-validator-4.0.2.GA.jar
jcl-over-slf4j-1.5.10.jar
joda-time-1.6.jar
jstl-1.2.jar
log4j.jar
slf4j-api-1.5.8.jar
slf4j-log4j12.jar
validation-api-1.0.0.GA.jar

Step 2. Create a web-Context.xml file under WEB-INF folder to hold web layer spring bean configuration. Here are the contents of the file:

		
		<?xml version="1.0" encoding="UTF-8"?>
		<beans xmlns="http://www.springframework.org/schema/beans"
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			xmlns:context="http://www.springframework.org/schema/context"
			xmlns:mvc="http://www.springframework.org/schema/mvc"
			xsi:schemaLocation="
				http://www.springframework.org/schema/beans	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
				http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
			
			<!-- Enable annotation driven controllers, validation etc... -->
			<mvc:annotation-driven />
			
			<!-- Controllers package -->
			<context:component-scan base-package="com.inflinx.blog.bookstore.web.controller" />
		
			<!-- JSP page location -->
			<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
				<property name="suffix" value=".jsp"/>
			</bean>
			 	
		</beans>
			
	

Step 3. Add Spring MVC Dispatcher Servlet to web.xml file. In the declaration below, Spring MVC will handle all URL requests to html pages.

		
		<?xml version="1.0" encoding="UTF-8"?>
		<web-app version="2.5" 
			xmlns="http://java.sun.com/xml/ns/javaee" 
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
			xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
			http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
			  
		  <servlet>
				<servlet-name>bookstore</servlet-name>
				<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
				<init-param>
					<param-name>contextConfigLocation</param-name>
					<param-value>/WEB-INF/web-Context.xml</param-value>
				</init-param>
				<load-on-startup>1</load-on-startup>
			</servlet>
		
			<servlet-mapping>
				<servlet-name>bookstore</servlet-name>
				<url-pattern>*.html</url-pattern>
			</servlet-mapping>
		
		</web-app>
		
	

Step 4. Create a Book domain object to hold information about a book:

		package com.inflinx.blog.bookstore.domain;

		public class Book
		{
			private String name;
			private String description;

			public String getName()
			{
				return name;
			}
			public void setName(String name)
			{
				this.name = name;
			}
			public String getDescription()
			{
				return description;
			}
			public void setDescription(String description)
			{
				this.description = description;
			}

			@Override
			public String toString()
			{
				return "Name: " + name + ", Description: " + description ;
			}
		}	
	

Step 5. Create a BookFormController to prepare the form and process form submission

		package com.inflinx.blog.bookstore.web.controller;
		
		import java.util.Map;
		
		import org.springframework.stereotype.Controller;
		import org.springframework.web.bind.annotation.RequestMapping;
		import org.springframework.web.bind.annotation.RequestMethod;
		
		import com.inflinx.blog.bookstore.domain.Book;
		
		@Controller
		@RequestMapping("/book.html")
		public class BookFormController
		{
			// Display the form on the get request
			@RequestMapping(method=RequestMethod.GET)
			public String showForm(Map model)
			{
				Book book  = new Book();
				model.put("book", book);
				return "form";
			}
			
		}
	
	

Step 6. Create form.jsp page with a form to capture book details:

	
		<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
		<html>
			<head></head>
			<body>
				<form:form method="post" action="book.html" commandName="book">
					<table>
						<tr>
							<td>Name:</td> <td><form:input path="name" /></td>
						</tr> 
						<tr>
							<td>Description:</td> <td><form:textarea path="description"/></td>
						</tr>
						</table>
					<input type="submit" value="Create" />
				</form:form>
			</body>
		</html>
	
	
	

The form will be submitted to the book.html page.

Step 7. Modify BookFormController to read the submitted data and process it.

		
		// Process the form. 
		@RequestMapping(method=RequestMethod.POST)
		public String processForm(Book book, Map model)
		{
			// Persistence logic to save the book will go here

			// Add the saved book to the model
			model.put("book", book);
			return "result";
		}	
	

Step 8. Create a result.jsp page to display the form submission result:

		<html>
			<body>
				${book.name} is stored in the database
			</body>
		</html>
	

Deploy the application and go to http://<yourserver:port>/bookstore/book.html. The page should present a form shown below:

Form

Form

Enter the book name “Test Book” and submit the form. You should see a screen that looks similar to image below:

Form Submission Result

Form Submission Result

 

2 Adding JSR 303 validation

Consider the following validation requirements to the book class:
a. Name and Description cannot be null or blank
b. Description cannot be more than 50 characters

Here are the steps to add the above validation requirements:

Step 1. Add @NotEmpty and @Size annotations to the name and description files of the Book class

		public class Book
		{
			@NotEmpty
			private String name;
			
			@Size(min=1, max=50)
			private String description;
			
			// Getters and setters here	
		}
	

NotEmpty annotation is not part of JSR 303 specification. It is part of Hibernate Validator framework which is the reference implementation for JSR 303.

Step 2. Modify BookFormController to have Spring validate the submitted data. This is done by adding a @Valid annotation before the book method parameter. The result of the validation can be accessed using the BindingResult method parameter.

		// Process the form. 
		@RequestMapping(method=RequestMethod.POST)
		public String processForm(@Valid Book book, BindingResult result, Map model)
		{
			if(result.hasErrors())
			{
				return "form";
			}
			// Persistence logic to save the book will go here

			// Add the saved book to the model
			model.put("book", book);
			return "result";
		} 	
 	

Step 3. Modify the form.jsp so that error messages can be displayed:

 		<form:form method="post" action="book.html" commandName="book">
					<table>
						<tr>
							<td>Name:</td> <td><form:input path="name" /></td> <td><form:errors path="name" /></td>
						</tr> 
						<tr>
							<td>Description:</td> <td><form:textarea path="description"/></td> <td><form:errors path="description" /></td>
						</tr>
						</table>
					<input type="submit" value="Create" />
		</form:form>
 	

Redeploy the application and when you submit an empty form, you should see validation failure messages next to the fields:

Validation Failed

Validation Failed

 

3 Customizing error messages

The validation failure messages in the image above are default to the framework. To make custom error messages appear follow these steps:

Step 1. Create a messages.properties file under the WEB-INF folder. Add the following messages:

   		NotEmpty.book.name=Name is a required field
		Size.book.description=Description must be between 1 and 50 characters
   	

Each message above follows this convention:

<CONSTRAINT_NAME>.<COMMAND_NAME>.<FIELD_NAME>

Step 2. Let Spring know about the newly created properties file. This is done by modifying the web-Context.xml file to include this bean declaration:

   	
			
	
    

Redeploy the application and submit an empty form. This time you should see custom error messages appear next to the fields:

Custom Validation Failed Messages

Custom Validation Failed Messages

 

Download the source code for this post here. The application is tested on Glassfish 3.0 and WebLogic 10.3.

 

weblogic.xml deployment descriptor

December 31st, 2009 1 comment

If you are using 10.3.0 version of Weblogic here is a sample weblogic.xml file with correct schema information:




			
	YOUR_APPLICATION_CONTEXT_NAME
	


And here is a sample weblogic.xml file for version 10.3.2 version:





     	YOUR_APPLICATION_CONTEXT_NAME



If you use the wrong version file, you might end up with exceptions like this:

com.bea.xml.XmlException: failed to load java type corresponding to e=weblogic-web-app@http://xmlns.oracle.com/weblogic/weblogic-web-app
at com.bea.staxb.runtime.internal.UnmarshalResult.getPojoBindingType(UnmarshalResult.java:361)
at com.bea.staxb.runtime.internal.UnmarshalResult.determineTypeForGlobalElement(UnmarshalResult.java:316)
at com.bea.staxb.runtime.internal.UnmarshalResult.determineTypeForGlobalElement(UnmarshalResult.java:326)
at com.bea.staxb.runtime.internal.UnmarshalResult.determineRootType(UnmarshalResult.java:307)
at com.bea.staxb.runtime.internal.UnmarshalResult.unmarshalDocument(UnmarshalResult.java:158)
Truncated. see log file for complete stacktrace

Categories: Solutions Log Tags: