Pages

Showing posts with label eclipse. Show all posts
Showing posts with label eclipse. Show all posts

Sunday, March 3, 2013

The legacy code that whispered to the developer

I was practicing my legacy code refactoring skills a bit this weekend (Highly on demand in the industry lately hehe..  ;) ) when I came across this fascinating line of code:

 System.out.println("Process complete!!!");  

My first thought was: "Whatever, just another silly console output nobody cares about!"
As usual, I run my eCobertura code coverage plugin to check how I was getting on with the level of coverage.
That line was red, it didn't bother me much so I continued with the rest of my testing and I said to myself, "I will come back to it latter...".

I was almost done when my torrent software notified me that a movie just finished downloading.
Also I started to feel hungry...  I wanted to go make lunch and enjoy the movie. "Let's continue with the practice another day..." I said to myself.

After making a sandwitch I came back to my laptop with the intention of watching the movie, but my eclipse IDE was still open. And that line that eCobertura painted red, was still there looking at me:


Suddenly it started talking to me and we had a very interesting conversation:

Line 43(In a thretening tone): "Psss!... hey you!..."

Djordje: "Are you talking to me?"

Line 43: "Do you see somebody else in the room? Yes, i am talking to you" 

Djordje: "Who do you think you are taliking to like that?"

Line 43: "I am a piece of untested code in your software. If you are adding code coverage I also have the right to get some."

Djordje: "Why should I unit test you? You are just a piece of old legacy nobody cares about"

Line 43: "You are such a dumb ass, you don't get it!"

Djordje: "Get what? Leave me alone I want to enjoy my sandwitch and watch my pirate movie. Don't make an scene because I will close the IDE and I will not practice with this program never again"

Line 43: "Ok, ok... take it easy! I just want to help you. Please, let's make a deal."

Djordje: "What deal?"

Line 43: "Just spend 5 more minutes trying to unit test me and I will teach you something important."

Djordje: "Fine, just 5 minutes. This better be good, because I am very hungry"

Poor Line 43, probably it just wanted to talk to somebody. What can I learn about TDD from such a simple line of code?  Anyway I decided to make it's wish come true and paint it green with eCobertura. This is what I did:

   private PrintStream originalConsoleOutput = new PrintStream(System.out); 
   private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); 
   @Before  
   public void setUpStreams() {  
     System.setOut(new PrintStream(outContent));  
   }  
   @After  
   public void cleanUpStreams() {  
     System.setOut(originalConsoleOutput);  
   }  
      @Test  
      public void  
      when_the_process_is_complete_show_a_message  
      ()   
      {
           //..   
           statistics.process();  
           assertEquals("Processing completed!!!\n", outContent.toString());  
      }  

Basically  what I did was just asserting that the console output is the same that what the println() command has in its argument. The process() method is where Line 43 was, so its content will go to the console when statistics.process() gets executed. At the end the method @After will restore the console output to the original stream that was previously saved.


Djordje"I painted you green. Are you happy now?"

Line 43"Thank you very much!....Thanks, thanks.... I am so happy now other lines of code will not look me over the shoulder or whisper to each other. They use to say _There is Line 43, did you know that the developer who created it was drunk... I can now walk onto the compiler with my head up..."


Djordje: "Whatever!, You are green, please just be quiet. Are you leaving me alone now?..."

Line 43: "Yes I will leave you alone, bye bye..."

Djordje: "Hey wait a second!... You told me that you would tell me something important if i get you green. What is it?"

Line 43: "Sorry I almost forgot."

Djordje: "Spit it out!"

Line 43:  "Many times when working in legacy software, developers use the so called _poor man technique. They fill the code with print commands to see the contents of the objects, the problem is that they often forget to remove them. But other times there are other print commands that are valid and really are meant to be there. In occasions, it is hard to distinguish what should be tested and what should not be. The rule is: If your application outputs valid information to the console and this is the only way you can test it, then it is correct to do it. But if you can avoid testing the console or other UI's by testing some related methods(sometimes in controllers), then you don't need to test the UI's. Remember that UI's, databases, frameworks and others... should be considered just addons, to our business layer(which at the end of the day is what provides the real business value)." Djordje: "Aaaaghhh... I hate you!"

Line 43"But why?"

Djordje: "My sandwitch is cold!"

Thursday, February 21, 2013

SVN merge operations in eclipse


When in source control slang when we talk about “merge” we refer to the act of applying specific software changes from one version into another.
“Merge” is a very important operation when working in large projects and version control tools such as subversion are of great help to the developers(I feel confident enough to say that today without this tools it would be almost impossible to work in a large scale project).
In this post I would like to describe just one of the many scenarios where “merge” is often used in real life and how we can perform this operation with the eclipse IDE:

Scenario example:
-Team Lead: Djordje, I was informed that the last bug fix will not just go into our next release, to the pre-production environment, we will also need to apply those changes to one of our older branches.

-Djordje: We have this fix currently in preproduction so you want to apply it also to a different branch? Why is that?

 -Team Lead: Yes, one of our principal test engineers think that something might remain untested and he would like to write some more tests, since those test were initially not part of our regression test plan, we don’t want to include them  to our trunk until they are approved by a business analyst, so what we are going to do is apply the changes to a separate branch test and merge back once the testing is complete and approved.

-Djordje: Understood, just give me the details of the branch where we want to perform the testing, I will prepare the environment for the test engineer.

-Team Lead: You will have to this in the support branch 5.6
-Djordje: Thanks, I will let you know when it is ready.




So the instructions were very clear, we will need to take the changes I did commit the other day into the pre-production environment and merge them to the support branch 5.6.
The first step is to make sure that eclipse is configured to use the merge implementation from our source control provider. For that we will just go to the Preferences menu and find Diff/Merge under the SVN option.


Since we use maven as a building tool, we will right click on the root of the project or the root module(where the parent pom.xml is) and find the merge option.



In this menu, make sure that in the “From:” field you select the path to the place where the changes are and in the “To”, place the destination branch.


When you click on the “Select…” option in the top, you will be able to pick the revision that contains your changes.

Note: You will notice that the revision number appearing on the field will be  below the one you selected. This will allow the merge operation can see the changes.

Now the task is completed the only thing needed is to commit the changes made to the branch.
When the engineer in our example finishes with the testing, the new tests can be merged back into the main development branch(trunk), performing the exact same operation but this time from the branch into the trunk.

Just for finishing this post, I would like to mention that in many occasions the terminology might get us confuse in the workplace and many people(often not technical), refer to this operation as a patch.
From my point of view, a patch is something different(Soon in a separate post I will talk about how to perform a patch).




Sunday, January 13, 2013

How to create a new JSF 2.1 project and deploy it in JBoss 7 AS

In this post I want  to document the process that needs to be done for creating JSF 2.1 project that supports servlet 3.x .
Also I will briefly explain how to install JBoss 7 AS and deploy the app.

Minimum requirements: JDK 6, maven 3,eclipse IDE, m2e plugin installed in eclipse

Creating a JSF 2.1 project

From your terminal, navigate to your workspace and execute the following command(change the name of the package and project with your own)
 mvn archetype:generate -DinteractiveMode=n -DarchetypeArtifactId=maven-archetype-webapp -Dversion=0.0.1-SNAPSHOT -DgroupId=com.yourpackagename -DartifactId=your_project_name  

Import the project in your eclipse IDE


Include the source folder src/test/resources 
This step maybe is not needed(depending the version of eclipse you are using), but my eclipse(STS-Juno) does not show some of the source folders when importing a maven project.
If you are experiencing this issue also, the way to solve it is:

right click on project->Build Path->New Source Folder...

This will make eclipse show all the required source folders. This is how it should look like:
In the pom.xml we need to add the JSF 2.1 dependencies and also the maven-compiler-plugin.
It should look like this:

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
      <modelVersion>4.0.0</modelVersion>  
      <groupId>com.yourpackagename</groupId>  
      <artifactId>your_project_name</artifactId>  
      <packaging>war</packaging>  
      <version>0.0.1-SNAPSHOT</version>  
      <name>your_project_name Maven Webapp</name>  
      <url>http://maven.apache.org</url>  
      <repositories>  
           <repository>  
                <id>maven2-repository.dev.java.net</id>  
                <name>Java.net Repository for Maven</name>  
                <url>http://download.java.net/maven/2</url>  
           </repository>  
      </repositories>  
      <dependencies>  
           <dependency>  
                <groupId>com.sun.faces</groupId>  
                <artifactId>jsf-api</artifactId>  
                <version>2.1.0-b03</version>  
                <scope>compile</scope>  
           </dependency>  
           <dependency>  
                <groupId>com.sun.faces</groupId>  
                <artifactId>jsf-impl</artifactId>  
                <version>2.1.0-b03</version>  
                <scope>compile</scope>  
           </dependency>  
           <dependency>  
                <groupId>javax.servlet</groupId>  
                <artifactId>jstl</artifactId>  
                <version>1.2</version>  
           </dependency>  
           <dependency>  
                <groupId>junit</groupId>  
                <artifactId>junit</artifactId>  
                <version>3.8.1</version>  
                <scope>test</scope>  
           </dependency>  
      </dependencies>  
      <build>  
           <plugins>  
                <plugin>  
                     <groupId>org.apache.maven.plugins</groupId>  
                     <artifactId>maven-compiler-plugin</artifactId>  
                     <version>2.3.2</version>  
                     <configuration>  
                          <source>1.6</source>  
                          <target>1.6</target>  
                          <encoding>UTF-8</encoding>  
                     </configuration>  
                </plugin>  
           </plugins>  
      </build>  
 </project>  

At this point if you did press ctrl+s you will notice that eclipse displays an error.
The reason is that the project does not contain yet all that is mentioned in the pom.xml. To synchronize what you should do is:

right click on project->Maven->Update Project...

The next thing we will do is configure the web.xml file to include the the Faces Servlet and also to make it compatible with Servlet 3.0 The web.xml file can be found under the WEB-INF/ folder


This is how the web.xml should look like:

 <?xml version="1.0" encoding="UTF-8"?>  
 <web-app 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_3_0.xsd"  
   version="3.0">  
      <display-name>Archetype Created Web Application</display-name>  
      <context-param>  
           <param-name>javax.faces.PROJECT_STAGE</param-name>  
           <param-value>Development</param-value>  
      </context-param>  
      <servlet>  
           <servlet-name>Faces Servlet</servlet-name>  
           <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>  
           <load-on-startup>1</load-on-startup>  
      </servlet>  
      <servlet-mapping>  
           <servlet-name>Faces Servlet</servlet-name>  
           <url-pattern>*.xhtml</url-pattern>  
      </servlet-mapping>  
      <welcome-file-list>  
           <welcome-file>home.xhtml</welcome-file>  
      </welcome-file-list>  
 </web-app>  

I don't want to explain all the details in this file, the most important thing is that it should be using version 3.0(The maven-compiler-plugin that we are using in our pom.xml is capable of parsing this). Also notice that the faces servlet is included, this is mandatory in order JSF to work,but the load-on-start-up tag is optional.

The next thing I will do is include the file faces-config.xml(optional) This is not mandatory since JSF 2.0 because with the use of annotations our managed beans will be automatically be loaded and there is no need to specify them in the deployment descriptor.
But the reason why I am doing so is: some web containers such as tomcat or jetty depending on the version, might not load our managed beans based on the annotations, so the faces-config.xml it is still required.
I discovered this,once while using an embedded tomcat 6 provided by maven when using mvn tomcat:run So this is how your faces-config.xml should look like if you decide to create it:

 <?xml version="1.0" encoding="UTF-8"?>  
 <!-- This file is not required if you don't need any extra configuration. -->  
 <faces-config version="2.1"  
   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-facesconfig_2_1.xsd">  
   <!-- Write your navigation rules here. -->  
   <application>  
             <locale-config>  
       <default-locale>en</default-locale>  
       <supported-locale>en</supported-locale>  
     </locale-config>  
   </application>  
 </faces-config>  

Before exiting the WEB-INF folder we will add just one more thing.
A folder called classes, with an empty file called beans.xml.
If we want to use CDI beans in our JSF project, this will be mandatory
At this point this is how the WEB-INF folder should look like:

This is all the configuration we needed to do in order to work with JSF.

NowI will just create a managed beand that returns some value to the page to prove that everything is well configurated.

 package com.yourpackagename;  
 import javax.faces.bean.ManagedBean;  
 @ManagedBean  
 public class Hello {  
      public String getMessage() {  
           return "www.javing.blogspot.com";  
      }  
 }  

Notice that in the web.xml the welcome page is called home.xhtml, so lets create that page in the webapp directory. (You can delete the index.jsp that was there by default)

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
      xmlns:ui="http://java.sun.com/jsf/facelets"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:h="http://java.sun.com/jsf/html"  
      xmlns:p="http://primefaces.org/ui">  
 <h:head>  
      <title>www.javing.blogspot.com</title>  
 </h:head>  
 <h:body>  
                <h:outputText value="#{hello.message}"/>  
 </h:body>  
 </html>  

Installing and deploying in JBoss7 AS
I suppose you know that you can download JBoss 7 AS for free from www.jboss.org, I just forgot the exact link to the download section, but it should not be to complicated to find. The one I am using is the linux distribution of jboss-as-7.1.1.Final.
So once you downloaded it, place the folder wherever you want, and set the environment variables.

This is how I did setup the environment variables for my user in the file ~/.profile (ubuntu 12.10):

 export PATH="/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:$  
 export JAVA_HOME=/usr/lib/jvm/jdk1.6.0_38  
 export M2_HOME=/usr/local/apache-maven-3.0.4  
 export M2=$M2_HOME/bin  
 export JBOSS_HOME=/home/djordje/jboss-as-7.1.1.Final  
 export PATH=$M2:$PATH:$JAVA_HOME/bin:$JBOSS_HOME/bin  
 export UNITY_LOW_GFX_MODE=1  

So now that your JBoss is installed correctly you can deploy the app we created before.
To do so, navigate to the project in the workspace and type the following command:

 /your_project_name$ mvn package  

That will generate a .war file in your target folder:

It is important to rename it correctly before deploying it.
This is how it should look like:


Now that we have the project packaged and ready to deploy, move that file into the deployments folder of the application server:


Now you have to start the application server, to start JBoss 7 in standalone mode.
Navigate to jboss-as-7.1.1.Final/bin/ and execute the script ./standalone.sh
You should see a message in the console that says: Deployed "your_project_name.war"

The last step is to navigate to the application typing this into the browser:

http://localhost:8080/your_project_name/home.xhtml








Tuesday, November 6, 2012

How to print into a remote application server log with eclipse.




  1. From the debug perspective access the debug configurations
  2. Use the Remote Java Application option in the debug menu to create a new debug configuration.
  3. Enter the ip of the remote host and the debug port.
  4. Click on Debug
  5. Once the debugger is hooked, open the display view
  6. Type the command you want to execute and execute it.
  7. tail -f of vi into server.log file to see the results

Monday, August 13, 2012

Subversion Native Library Not Available

Did you ever have to deal with this annoying Subversion update message when Starting your Eclipse IDE?


To avoid it popping up, just go to your preferences and change the SVN interface.


Share with your friends