Dave Harris

General ramlings about Java

How to access the Spring WebFlow from Spring MVC September 1, 2009

Filed under: How-to, Spring — daveharris @ 5:09 pm

I recently came across a problem in a Spring Webflow based application where I needed to have one page as a standard Spring MVC page.  I needed to write a PDF file to the actual http response and I’m not allowed to do that in WebFlow.

So I defined a standard Spring MVC Controller and URL Mapper to complement my existing Flow Controller:

<bean id="PDFPageController" class="controller.mvc.PDFPageController" />

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
  <property name="mappings">
    <props>
      <prop key="/index.htm">/index.htm</prop>
      <prop key="/pdf.htm">PDFPageController</prop>
    </props>
  </property>
</bean>

<bean name="/index.htm" class="org.springframework.webflow.executor.mvc.FlowController">
  <property name="flowExecutor" ref="flowExecutor" />
  <property name="defaultFlowId" value="main" />
</bean>

Then inside the MVC Controller (which extends AbstractController), define a method called accessFlowScope like below:

private void accessFlowScope(HttpServletRequest request, HttpServletResponse response) {
  // Gain access to the Spring Web Flow context
  FlowController controller = (FlowController)getApplicationContext().getBean("/index.htm");
  FlowExecutionRepository repository = ((FlowExecutorImpl)controller.getFlowExecutor()).getExecutionRepository();
  FlowExecutorArgumentHandler handler = controller.getArgumentHandler();
  ExternalContext externalContext = new ServletExternalContext(getServletContext(), request, response);

  // Make sure we have a flow execution key.
  if (handler.isFlowExecutionKeyPresent(externalContext)) {
    try {
      // Get access to the variable stored in the context.
      ExternalContextHolder.setExternalContext(externalContext);
      FlowExecutionKey flowExecutionKey = repository.parseFlowExecutionKey(handler.extractFlowExecutionKey(externalContext));
      FlowExecution flowExecution = repository.getFlowExecution(flowExecutionKey);
      Object variableInFlowScopeObject = flowExecution.getActiveSession().getScope().get("variableInFlowScope");
    }
    catch(Exception ex) {
      logger.error("Error when accessing flow scope from MVC", ex);
    }
    finally {
      ExternalContextHolder.setExternalContext(null);
    }

  }
  else {
    logger.error("Handler did not have flow execution key present");
  }
}

This can then be called from your handleRequestInternal method of the MVC controller:

public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)

All that is required now is to call from the Webflow view jsp into the MVC controller.  I had to do a horrible iframe like so:

<iframe id="pdf-view" src="pdf.htm?_flowExecutionKey=${flowExecutionKey}" height="100%" width="50%">
  I'm sorry, iframes are not supported by your browser, upgrade to <a href="http://getfirefox.com">Firefox</a>
</iframe>

Now you can pull out whatever values you require from the many scopes (request, flash, flow, conversation) and use them in your MVC controller to do stuff.

NB: All the code is used pretty much verbatim from http://www.ervacon.com/products/swf/tips/tip1.html, but it doesn’t say to add the flowExecutionKey onto the URL, which is the part I was missing and thiking that it wasn’t working correctly.

 

SVN Dump Parts of a Repository August 5, 2008

Filed under: How-to — daveharris @ 5:02 pm

Today at work at Fronde I needed to create a dump of a ‘project’ inside a repository.  Our SVN setup is to have one repo per team and then within there have a folder for each client/project.  In this case I was providing the backup to a client so it was vital that I gave them just their code and not the whole repo.

So my SVN repo was like this:

/
  teamA
    clientA
    clientB
  teamB
    clientC

To dump the clientA history into a portable, re-creatable format, I used svnadmin dump, like this:

svnadmin dump [path to repo] > C:\Repo.svn-dump

Which creates a dump of the entire repository at C:\Repo.svn-dump.  This took about 10 mins with 1000 versions and used 100% so it would be best to perform this outside of normal work hours.  You have been warned!

I then used svndumpfilter (tutorial) to filter just for the ClientA folder (see folder tree above):

svndumpfilter include ClientA < Repo.bak > ClientA.bak

This didn’t take very long and at the end I had a full svn repository that could be re-created anywhere.  To prove the point I installed SVN on my mac and created the repository.  I then loaded the dump file into it and it worked beautifully ;)

svnadmin create /Users/Dave/ClientA
svnadmin load /Users/Dave/ClientA < ClientA.bak
mkdir /Users/Dave/ClientA-checkout
svn co file:///Users/Dave/ClientA clientA-checkout/

Now that you have checked it, you can delete the whole repo backup file (mine was massive) Repo.svn-dump in my case.

Easy as pie once you know how.  The fact that you can’t specify the filter at dump-time is non-intutative, clunky and frankly a waste of space.  However if you only need to do it once it works and produces a very nice result.  Open Source and Open Standards FTW ;)

 

MySQL Backup Script May 29, 2008

Filed under: *nix, How-to — daveharris @ 12:53 pm

This is a convienct place for me to put stuff that I (or you!) may need in the future. While working at Fronde I wrote this little backup script for the wiki we were using. It is meant to be run on a cron job daily. It makes daily backups and every Friday copies that backup to elsewhere (preferably off disk or off site) and deletes that past week’s daily backups. Before I get flamed in the comments I know that there is AutoMySQLBackup but that is huge and very complicated and I wanted to write it myself! :P

#!/bin/bash
# Wiki Database backup script

# Set up the variables
DB_USERNAME="username"
DB_PASSWORD="password"
DB_HOST="localhost"
DB_NAME="wikidb"
BACKUP_DIR="~/wiki_backups"
ARCHIVE_DIR="~/wiki_backups/archive"
DATE=$(date '+%Y-%m-%d')
OUTPUT_FILENAME="${BACKUP_DIR}/wiki_${DATE}.sql"
ERROR_FILENAME="${BACKUP_DIR}/error_log_${DATE}.txt"
ARCHIVE_FILENAME="${ARCHIVE_DIR}/wiki_${DATE}.sql"
MYSQLDUMP="/usr/local/mysql/bin/mysqldump"

# Dump the wiki db to a file
${MYSQLDUMP} -ac --add-drop-table -u ${DB_USERNAME} --password=${DB_PASSWORD} \
    -h ${DB_HOST} -r ${OUTPUT_FILENAME} ${DB_NAME} &> ${ERROR_FILENAME} 

# If there are errors, then do stuff here...
STATUS_CODE="$?"
if [ ${STATUS_CODE} = 2 ]; then

fi

# If the error log is empty, delete it
numLines=$(cat ${ERROR_FILENAME} | wc -l | sed 's/\ //g')
if [ ${numLines} = 0 ]; then
  rm ${ERROR_FILENAME}
fi

# If today is Friday, put a weekly backup in archives and delete daily backups
if [ $(date +%A) = "Friday" ]; then
  cp -f ${OUTPUT_FILENAME} ${ARCHIVE_FILENAME}
  rm ${BACKUP_DIR}/*.sql
  #echo $(cat ${BACKUP_DIR}/wiki_${DATE}.sql)
fi
 

VLOOKUP Excel Function March 19, 2008

Filed under: How-to — daveharris @ 9:04 am
Tags:

Have you ever had list of status flags that have a meaning and within excel be able to change the number for the actual meaning? Then this is for you!

Assume you have this data:

Customer Id Payment Type
1 2
2 0
3 1

And you have a set of Payment Types:

Payment Type Code Payment Description
0 Cash
1 Eftpos
2 Credit Card

If you have this data in an Excel spreadsheet you can use the VLOOKUP Function to translate these numbers into meanings. The VLOOKUP function is defined as VLOOKUP(lookup_value, table_array, col_index_num, range_lookup) where:

  • lookup_value: the id that is to be looked up
  • table_array: the table which holds the key and the value (can be on another sheet)
  • col_index_num: the column number within the table which holds the value
  • range_lookup: boolean to specify if ‘approximate’ values should be looked up

Therefore a simple formula could be: =VLOOKUP(B15, A26:B29, 2, FALSE)

If you need to perform this action on a whole table of data and need to keep it in a constant column, and the lookup table is on another sheet, this can be used: =VLOOKUP(B2,Sheet2!$A$2:$B$5, 2, FALSE)

I cannot claim the credit for this albeit simple and well-documented function, all credit goes to Phil Wheeler

 

How can I convert ASCII characters to ISO8859? November 6, 2007

Filed under: How-to — daveharris @ 8:55 pm

I’ve had this little problem for a while now and can’t fix it so ive resrted to asking the guru’s at Sun’s java forums.  You can see my post here

If you can help me, please answer it there for all to see, and post a comment on here ;)

Dave

 

OSx86 with nVidia 7600gt August 8, 2007

Filed under: How-to, Mac, OSx86 — daveharris @ 7:58 am
Tags:

This is quick and dirty how-to to get Quartz Extreme and Core Image at full resolution working on OSx86 (with OSX 10.4.8) a nVidia 7600gt 256MB card.

Follow the simple insructions below and you can’t go wrong:

  • Install OSx86 with the optional Natit package
  • Once booted find your card identifier by adding the DeviceID and VendorID together to get a string (mine is 0×02e110de)
  • Edit the corresponding <string> tag for the IOPCIMatch key in these four packages (in /System/Library/Extensions)
    • Geforce.kext
    • NVDANV40Hal.kext
    • NVDANV30Hal.kext
    • NVDAResman.kext

    If the file is like this:
    <key>IOPCIMatch</key>
    <string>0×00000000&0×0000ffff</string>
    Replace it with this:
    <key>IOPCIMatch</key>
    <string>0×02e010de&0×0000ffff</string>

    If the key has a number of values in the string tag, just add 0×02e010de&0×0000ffff to the start of the list.

  • You now need to flush the kext cache so run the following:
    sudo rm /System/Library/Extensions.*
  • Now reboot and enjoy the goodness of Mac OSx86 :)

I cannot claim the credit for this, I got it from this forum here http://www.osxx86.info/vbulletin/showthread.php?t=1514 by a post by sinjon (shot mate ;) )

 

Starting services at boot in Redhat Linux July 31, 2007

Filed under: *nix, How-to — daveharris @ 4:40 am
Tags:

This is how to set a program (or daemon) to run at boot. For example, if you want to run at cron at boot (which you would) issue the following as root.

/sbin/chkconfig –add crond
/sbin/chkconfig –level 2345 crond on

You can then confirm that it has worked by looking at /etc/rc.d/rc2.d/S<number>crond (eg S90crond).

 

How to configure cache-control in Tomcat July 9, 2007

Filed under: How-to — daveharris @ 11:42 pm
Tags: ,

I ran into a major problem with IE (*shudder*) not being able to open files. I could save them fine, but when I went open, the application would complain that it couldn’t find the file. I found that the problem was not the java application but the webserver itself. Using a very useful tool called Fiddler I looked at the HTTP request headers and found that the webserver was overwriting the headers I set in java. I found that the headers were:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Date: Mon, 09 Jul 2007 22:50:18 GMT
Content-type: application/octet-stream
X-powered-by: Servlet/2.4
Pragma: No-cache
Cache-control: no-cache
Expires: Thu, 01 Jan 1970 12:00:00 NZST
Content-disposition: attachment; filename=trace-64.pcap
Transfer-encoding: chunked

Setting no-cache means that IE downloads the file, but then it expires it in cache, it gets deleted and hence the application cannot open the file. After much searching around the internet, I found this post which describes how to do it.

I added the below to my META-INF/context.xml:

<Valve className="org.apache.catalina.authenticator.BasicAuthenticator"  disableProxyCaching="false" />

Once Tomcat is restarted, the headers are now:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Disposition: attachment; filename=trace-4.pcap
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Date: Mon, 09 Jul 2007 22:59:01 GMT

IE now can open files!!!!!!!!! Credit goes to above post ;)
This works for me when included in the .war file, and it now works in Firefox and IE.