Sunday, October 26, 2014

pageContext.request.contextPath returns "/" instead of empty string [FIXED]

Recently I was creating a Spring application hosted on Heroku and realized that ${pageContext.request.contextPath} was returning "/" instead of "" for application deployed on root.

When "" (Empty String) is returned:

Ideally the contextPath should not end with slash "/" because we will be using it in the urls like given below:

 <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">  

so here url in my local machine would map to something like

 <link href="/my-app-name/resources/css/bootstrap.min.css" rel="stylesheet">  

and when run from the remote server, it should map to something like

 <link href="/resources/css/bootstrap.min.css" rel="stylesheet">  

When "/" is returned:

When the contextPath wrongly returns "/" my urls are wrongly mapped like below (with double slash //):

 <link href="//resources/css/bootstrap.min.css" rel="stylesheet">  

Fix:

After a lot of research, I found the issue. Heroku uses webapp-runner. Version 7.0.34.0 returns "/" as context path and version 7.0.34.1 returns "". So upgrading webapp-runner to 7.0.34.1 solved the issue for me.

Saturday, October 25, 2014

FIX: Missing web.xml issue on Heroku when trying Spring Java Based Configuration

If you are trying to use Spring Java Based Configuration instead of web.xml and other xml configuration files on application hosted on Heroku, you might come across the following error:

 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.2:war (default-war) on project sg-compare: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode) -> [Help 1]

Fix:

In your pom.xml add

  <failOnMissingWebXml>false</failOnMissingWebXml>  

to the maven-war-plugin

Example:

Replace the following code

 <plugin>  
         <artifactId>maven-war-plugin</artifactId>  
         <version>2.2</version>  
 </plugin>  


with the following:

 <plugin>  
         <artifactId>maven-war-plugin</artifactId>  
         <version>2.2</version>  
         <configuration>  
                <failOnMissingWebXml>false</failOnMissingWebXml>  
         </configuration>  
 </plugin>  

Thursday, September 11, 2014

Fix for read timed out error after push to OpenShift

Sometimes in Eclipse, while trying to push a commit to OpenShift, we get "read timed out" error. The cause of the error is a setting in Eclipse which times out the push after 30 seconds.

In order to change the time out settings, do the following:

1. Open Window > Preferences

2. Click on Team > Git



3. Increase the "Remote connection timeout (seconds):" setting to something like 180.

4. Click OK to save the setting.

This should stop the error from occurring in future commits.

Wednesday, September 10, 2014

How to Upload and Serve files using Java Servlets on OpenShift (With FIXES)

This is a modified version of the code in this post  How-To: Upload and Serve files using Java Servlets on OpenShift. The original post was written by Corey, Red Hat, Inc. OpenShift (PaaS) Senior Product Marketing Manager @ Red Hat.

When I ran Corey's code, I came across few issues. So below code includes some fixes for those issues.

Issues:

1. Corey's code has issues on local server (Local Tomcat 7 running on Windows in my case)

2. Files with space in the file name fails to be served.

Fix:

First of all, open you windows environment variables window and add a new variable for OPENSHIFT_DATA_DIR





As you can see, I've created a folder D:\openshift\uploads\ and added it to the windows environment variable OPENSHIFT_DATA_DIR. You can use any folder of your choice. Just make sure that the folder is outside your project folder and git.

Now, change Corey's version of Uploads.java to look like below. Changes are highlighted in bold letters.


 import java.io.File;  
 import java.io.FileInputStream;  
 import java.io.FileOutputStream;  
 import java.io.IOException;  
 import java.io.InputStream;  
 import java.io.OutputStream;  
 import java.io.PrintWriter;  
 import java.net.URLDecoder;  
 import javax.activation.MimetypesFileTypeMap;  
 import javax.servlet.ServletException;  
 import javax.servlet.annotation.MultipartConfig;  
 import javax.servlet.annotation.WebServlet;  
 import javax.servlet.http.HttpServlet;  
 import javax.servlet.http.HttpServletRequest;  
 import javax.servlet.http.HttpServletResponse;  
 import javax.servlet.http.Part;  
 @WebServlet(name = "uploads", urlPatterns = { "/uploads/*" })  
 @MultipartConfig  
 public class Uploads extends HttpServlet {  
      private static final long serialVersionUID = 2857847752169838915L;  
      int BUFFER_LENGTH = 4096;  
      protected void doPost(HttpServletRequest request,  
                HttpServletResponse response) throws ServletException, IOException {  
           PrintWriter out = response.getWriter();  
           for (Part part : request.getParts()) {  
                InputStream is = request.getPart(part.getName()).getInputStream();  
                String fileName = getFileName(part);  
                FileOutputStream os = new FileOutputStream(  
                          System.getenv("OPENSHIFT_DATA_DIR") + fileName);  
                byte[] bytes = new byte[BUFFER_LENGTH];  
                int read = 0;  
                while ((read = is.read(bytes, 0, BUFFER_LENGTH)) != -1) {  
                     os.write(bytes, 0, read);  
                }  
                os.flush();  
                is.close();  
                os.close();  
                out.println(fileName + " was uploaded to "  
                          + System.getenv("OPENSHIFT_DATA_DIR"));  
           }  
      }  
      protected void doGet(HttpServletRequest request,  
                HttpServletResponse response) throws ServletException, IOException {  
           //Remove extra context path which exists in local Tomcat applications.  
           String filePath = request.getRequestURI().substring(  
                     request.getContextPath().length());  
           //Decode url. Fixes issue with files having space within the file name  
           filePath = URLDecoder.decode(filePath, "UTF-8");  
           File file = new File(System.getenv("OPENSHIFT_DATA_DIR")  
                     + filePath.replace("/uploads/", ""));  
           InputStream input = new FileInputStream(file);  
           response.setContentLength((int) file.length());  
           response.setContentType(new MimetypesFileTypeMap().getContentType(file));  
           OutputStream output = response.getOutputStream();  
           byte[] bytes = new byte[BUFFER_LENGTH];  
           int read = 0;  
           while ((read = input.read(bytes, 0, BUFFER_LENGTH)) != -1) {  
                output.write(bytes, 0, read);  
                output.flush();  
           }  
           input.close();  
           output.close();  
      }  
      private String getFileName(Part part) {  
           for (String cd : part.getHeader("content-disposition").split(";")) {  
                if (cd.trim().startsWith("filename")) {  
                     String filename = cd.substring(cd.indexOf('=') + 1);  
                     //remove extra file path in windows local machine  
                     return filename.substring(filename.lastIndexOf("\\") + 1)  
                               .trim().replace("\"", "");  
                }  
           }  
           return null;  
      }  
 }  

I've kept the above Uploads.java file in src/main/java. Here java folder is the source folder and the Uploads.java file is in the default package.

Folder structure (application created with OpenShift plugin on Eclipse):



Rest of the code and instructions are the same as in Corey's post How-To: Upload and Serve files using Java Servlets on OpenShift.

Hope this helps. Thanks Corey for your post, which gave the basic understanding of how upload works on OpenShift. Let me know if anyone needs help.

Have a great day!

Friday, September 5, 2014

Fixing Bootstrap IE 8 issue related to Navbar (collapsed like mobile version)

If you just noticed that on some IE versions your Navbar is collapsed like a mobile version even though you are viewing from a desktop browser, then you might be using CDN version of bootstrap.min.css

Possible Fix #1 (CDN Issue):


To fix the issue, you need to download bootstrap.min.css and place it in a subdirectory of your application, something like below:

/css/bootstrap/3.2.0/bootstrap.min.css

Related change in code:

If you are using bootstrap.min.css from a CDN like given below,

 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">  


then, replace the above code with a local version of bootstrap.min.css like given below:

 <link rel="stylesheet" href="./css/bootstrap/3.2.0/bootstrap.min.css">  


Keeping bootstrap.min.css within the application rather than on the CDN should solve the Internet Explorer issue.

Check the source of this Bootstrap Navbar example page for reference.

NOTE: If you are using  bootstrap.css instead of bootstrap.min.css the same solution is still applicable.

Possible Fix #2 (Locally run html file):

I've noticed that the IE8 issue still occurs if html file is stored locally and run from local IE8.

For example: D:\bootstrap-example.html

Instead, run the html through a web server like below:

http://example.com/bootstrap-example.html

or

http://localhost:8080/bootstrap-example.html

If you still have problems, please leave a comment below, I'll try to help you.

Thursday, September 4, 2014

Why this blog? Why Hands-On Coding?

Though there are a lot of resources available online for learning beginner and advanced programming concepts, I feel that there is still room for improvement on how programming lessons can be presented through a practical approach.

So, if you go through this blog, you should be able to get quickly started on building real world applications.

Hope you guys will like my approach.

Wish you all the best,
Blesson Jose