Oct 14

RESTful programming is all the rage these days – at least in Rails world. It's a simple way to perform request dispatching which is easy to understand and maps database CRUD operations into web requests elegantly. While Rails comes with REST routing built in, there is no such support in Spring MVC. However, Spring's decoupled design makes it rather easy to implement. Here's code I wrote to implement RESTful dispatches using Spring MVC.(Also available as a download here)

package com.yellowfish.servlets;
import javax.servlet.http.*;
 
import org.apache.log4j.*;
 
import java.util.*;
 
import org.springframework.web.servlet.mvc.multiaction.*;
 
public class RESTMethodResolver implements MethodNameResolver {
 
    public String getHandlerMethodName(HttpServletRequest req) throws NoSuchRequestHandlingMethodException {
 
        Logger log = Logger.getLogger("com.yellowfish.servlets");
 
        log.debug("Resolving method name for the Request");
 
        String method = req.getParameter("_method");
 
        String id     = req.getParameter("id");
 
        String http_method = req.getMethod().toUpperCase();
 
        String controller_method = null;
 
        log.debug("method: "+method+" http_method: " + http_method + " id: "+id);
 
        if(http_method.equals("GET")) {
 
            String uri = req.getRequestURI();
 
            controller_method =  (uri.endsWith("/new") ? "_new" : "show");
 
            if(controller_method == "show") {
 
                controller_method = (id == null) ? "index" : "show";
 
            }
 
        } else if(http_method.equals("POST")) {
 
            if(method != null) {
 
                method = method.toUpperCase();
 
                if(id == null)
 
                    throw new com.yellowfish.servlets.ServletException("id cannot be NULL for PUT and DELETE");
 
                if (method.equals("PUT"))
 
                    controller_method = "update";
 
                else if(method.equals("DELETE"))
 
                    controller_method = "delete";
 
            } else {
 
                controller_method = "create";
 
            }
 
        }
 
        if(controller_method == null) {
 
            log.debug("No Controller Method Found");
 
            throw new NoSuchRequestHandlingMethodException(null, this.getClass());
 
        }
 
        log.debug("Controller method resolved to :" + controller_method);
 
        req.setAttribute("controller_method_name", controller_method);
 
        if(id != null) {
 
            try {
 
                req.setAttribute("model-id", Long.valueOf(id));
 
            } catch(NumberFormatException exp) {
 
                log.warn("id" + id + " is not a Number");
 
            }
 
        }
 
        return controller_method;
 
    }
 
}

Then simply declare this bean in the spring config:

<bean class="com.yellowfish.servlets.RESTMethodResolver" id="rest-method-resolver"></bean>

It resolves incoming URL and Method as per following table:

 

 

REST Resolver Rules
URI GET/POST ID Parameter Present? _method Parameter Present? Method Name
 /server GET  No  N/A index
/server/_new GET No N/A new
/server?id=100 GET Yes N/A show
/server POST No  No create 
 /server POST  Yes PUT update 
 /server POST  Yes  DELETE delete 

 To make life simple, the code above assumes all IDs to be numeric and if ID is present in incoming request, it creates a Request attribute called 'model-id' . 

Tagged with:
Sep 21

The example at yaws web site to read the file upload is a good starting point but it's too simplistic. I extended the example so it's useful in the real world. (Update: Thanks to Steve Vinoski, this module(yaws_multipart) is now part of the yaws git tree).

  1. It reads all parameters – files uploaded and other simple parameters .
  2. It takes a few options to help file uploads. Specifically:
    1. {max_file_size, MaxBytes} : If file exceeds MaxBytes bytes, return an error
    2. no_temp_file: read the uploded file in memory without any temp files
    3. {temp_file,FullFilePath}: Specify full path for the temp file. If not given, a unique file name is generated
    4. {temp_dir, TempDir} : Specify a directory to store uploaded temp file. By default '/tmp' is used.

Using it is simple. Just call read_multipart_form from your 'out' function and it'll return a tuple with first element either 'get_more', 'done' or 'error'. The 'get_more' implies more data needs to be read and you must call read_multipart_form again. 'done' implies it's done reading all parameters and you're free to proceed. The 'done' tuple also returns a 'dict' full of params. This dict can be queried for parameters by name. For file upload parameters it returns one of the following lists:

[{filename, "name of the uploaded file as entered on the form"},
  {value, Contents_of_the_file_all_in_memory}]
OR
[{filename, "name of the uploaded file as entered on the form"},
  {temp_file, "full pathname of the temp file"}]

In the second case, it's your responsibility to remove the temp file. Usage example:

-module(my_yaws_controller).
-export([out/1]).
 
out(Arg) ->
     Options = [no_temp_file],
     case yaws_multipart:read_multipart_form(Arg, Options) of
             {done, Params} -> 
                   io:format("Params : ~p",[Params]),
                   [{filename, File_name},{value,File_content}] = dict:find("my_file", Params),
                  Another_param = dict:find("another_param", Params);
                  % do something with File_name, File_content and Another_param
              {error, Reason} ->
                   io:format("Error reading multipart form: ~s", [Reason]);
              Other -> Other
      end
.
Tagged with:
Jun 22

It’s hard for a business to survive today.  This has caused lot’s of companies to incorporate practically any method of prospecting new business such as constant cold calls, daily eblast, ineffectively designed direct mail, etc..

With a rapid fire of  sales genres being applied in attempt to win customers, the buyer is steadily becoming desensitized and blocking most of this crap out. The buyer knows they can just google a service / product  if they need to and become annoyed at the unwelcome sales contact. Obviously this leaves a bad taste in their mouth. In the end the buyer will be the one to approach a business should they decide to and only if the business is deemed worthy.

That’s why it’s super important that you have a professional web presence built and are positioned and ready to allow the buyer/searcher to find you first instead of you calling them. With most people starting their search for products or services on the web, they can do the research and check out places before they dive in and make contact.  Make sure your website is in good position out there delivering the information the searcher/buyer is looking to find.

When these buyers contact you via website, they  already know what you do and how you can help them.  By letting the prospect approach you, their perception of you is different. You will be a consultant to them, not a pesky peddler with unwanted goods that were not asked for.  That alone gives you a good chance at selling to them and gains you instant respect.

Think of  positioning your website vs. prospecting this way;  if you needed a doctor, you would research and choose one you felt comfortable with.  You probably wouldn’t choose the prospecting doctor who happen to call you at breakfast one week wondering if you had a migrane headache they could help with nor would you choose the prospecting doctor who sent you a flyer in the mail offering a significant new patient discount that expires in two weeks.

What it boils down to is the doctor doesn’t find the patient, the patient find them. This creates the patient confidence to accept the diagnosis and follow recommended orders no matter how inconvenient or painful.

Get competitive and make sure your website is out there and ready to be found when these potential customers start their research. Lastly, make sure your website is delivering information that will help the visitor get started, then want to contact you to learn more. That is website positioning, not prospecting.

Tagged with:
Jun 18

When considering your business website it’s best to think in terms of business goals you would like to achieve with your website. Your website is the front door of your business. Most people start searching for services and products these days on the web, then contact you in person or visit your physical location. With this in mind, think of what business goals you would like your website to meet as it is your first impression.  It’s the best business tool you’ve got, make it work hard for you and make it speak to your visitors.

Some business goals to consider (think in terms of a year from now, 2 years from now) when determining your website goals are:

What do you want your website to do for you AND the visitor?

  1. Inform
  2. Inspire Awareness
  3. Educate
  4. Repeat Visitors
  5. User Interaction
  6. Media source
  7. Resources
  8. Measurement
  9. Call-to-actions
  10. Funding/ donations
  11. Grow Rep & Branding

Qualitive Goals:

  1. Market Position
  2. Kind of Business
  3. Target Audience/ Market

Potential conflicts of business goals (if any):

Other Goals:

Other Challenges:

Once you have this handly list populated, a web designer will have a great tool to design a website that will  accommodate these needs. It’s truly helpful.

Tagged with:
preload preload preload