Warning: include_once(/home/ryamar39/gearandtechblog.com/wp-content/plugins/google-sitemap-pro/google-sitemap-pro.php): failed to open stream: Permission denied in /home/ryamar39/gearandtechblog.com/wp-settings.php on line 305

Warning: include_once(): Failed opening '/home/ryamar39/gearandtechblog.com/wp-content/plugins/google-sitemap-pro/google-sitemap-pro.php' for inclusion (include_path='.:/usr/local/lib/php:/usr/local/php5/lib/pear') in /home/ryamar39/gearandtechblog.com/wp-settings.php on line 305

Warning: Cannot modify header information - headers already sent by (output started at /home/ryamar39/gearandtechblog.com/wp-settings.php:305) in /home/ryamar39/gearandtechblog.com/wp-content/plugins/wp-super-cache/wp-cache-phase2.php on line 60

Warning: Cannot modify header information - headers already sent by (output started at /home/ryamar39/gearandtechblog.com/wp-settings.php:305) in /home/ryamar39/gearandtechblog.com/wp-includes/feed-rss2.php on line 8
Gear and Technology Blog http://www.gearandtechblog.com From the outdoors to the office Thu, 12 Nov 2015 02:33:14 +0000 en-US hourly 1 USB Cables, does premium equal better? http://www.gearandtechblog.com/2015/11/10/usb-cables-does-premium-equal-better/ http://www.gearandtechblog.com/2015/11/10/usb-cables-does-premium-equal-better/#respond Wed, 11 Nov 2015 04:06:08 +0000 http://www.gearandtechblog.com/?p=416

If you have been an electronics dork long enough you have been in an electronics store and heard a salesperson trying to sell a $100 HDMI cable, promising a huge advantage in picture and sound quality. I have never been a fan of super premium cables for digital signals, as long as the cable is shielded you can’t really degrade a digital signal, it either arrives to its destination or it doesn’t. You will get a picture or you won’t. If it meets specification for bandwidth you are golden.

Until now I have mistakenly applied this way of thinking to USB cables. My mistake was thinking of USB as only a means of data transfer despite the fact that it has been the standard for consumer electronics charging for quite a while now. I have always been fairly impressed by the fact that we are cramming 2.1A over 28-30AWG conductors without problem. I have assumed there was a voltage drop but never took the opportunity to measure it until now.

Anker has introduced a line of USB “charging and sync” cables promising “The World’s Fastest, Most Durable Charging Cable”. I decided to dissect one of these cables to determine if its marketing wank or fact. This will be a direct comparison between a generic USB micro and the Anker PowerLine Micro USB. The power supply used for the test is the Anker 5 port 40W USB charger with only 1 device attached.

DSC00568-smDSC00569-sm

DSC00570-sm DSC00571-sm

Testing methodology

This test is pretty simple, I will compare external quality and internal quality. I will measure the voltage drop while charging a high output LED flashlight containing two 18650 batteries. The flashlight is run until it turns off (approx 6.95v on the 7.4v cell), this increases the chance that I will get the maximum charging current during this test. I measured the load using my multimeter at 1.35 Amp. The battery is room temperature during tests to try to avoid any temperature based current throttling that may occur. I am not sure how complex the charging circuit is in these batteries so its unclear if this makes a difference.

 

External build quality

The Anker cable is a tank in comparison to the generic cable. It is quite a bit stiffer than the generic but that is to be expected, it is noticeably thicker. The molded connectors are nice and smooth and are comfortable to handle. A velcro tie is included with the cable to keep things tidy during storage. The strain relief portion of the molded connector is a tad shorter than the generic but the cable jacket appears to be well bonded to the connector. It is not possible to create a gap between the two by pulling on the cable. I would wager its fairly water tight.

The generic cable is exactly as you would expect, we all have one of these. Nothing about it is remarkable. The strain relief is loosely attached to the cable jacket, you can create a gap by pulling on the cable.

 

Internal build quality

The Anker cable is quite thick, now we can see why. It has two layers of shielding very similar to a coaxial cable. A thick braided shield and a thinner foil shield. The shielding is properly grounded to the shells on the USB connector. There is also a un-insulated ground that runs inside the shielding along the insulated conductors. The positive (VCC) conductor is very thick, I am guessing its 22AWG. The neutral/ground is handled by the shielding and the uninsulated GND conductor so there is plenty of material there. The data transmission conductors (D- white, D+ green) are in the 26-28AWG range which is more than adequate for carrying the ones and zeroes. The shells of both connectors are attached to the shielding as one would expect.

These two photos show the detail of the shielding. The outer braided shield and the inner foil shield. Very similar to what is found in RG59 coax. Click to view larger.

DSC00573-sm DSC00574-sm

Here you can see the large VCC (+5VDC) conductor. Note that I stripped some of the jacket away prior to taking this photo. Click to view larger.

DSC00575-sm

 

Test setup. 5.12VDC no load. 5.00VDC with the 1.35A load. Click to view larger.

DSC00579-sm DSC00578-sm

The generic cable has no shielding, the shells of both connectors are isolated from each other. All of the internal conductors (GND, D+, D-, VCC) are small diameter 28-30 AWG. This is probably fine for transmitting ones and zeroes but not so great for transmitting up to the 2.1A that is common for USB 2.0 devices. Note that the USB 2.0 charging specification allows up to 5A per section  7.2.1.2.1 of the Battery charging specification. Trying to pull 5A over this cable would be borderline dangerous. Even at this test’s 1.35A it gets warm almost instantly.

Showing the conductors of the generic USB versus Anker. Click to view larger.

DSC00580-sm

Test setup. 5.12VDC no load. 4.05VDC with the 1.35A load. Click to view larger.

DSC00581-sm DSC00582-sm

Thermal video captured using a FLIR ONE camera. This video demonstrates how inadequate a generic USB cable is with even a light charging load.

Generic USB with 1.35A load.

Anker Powerline USB with 1.35A load.

 

Anker cable after approx 10 minutes of charging. Minimal thermal change.

image1

 

 

The sample Anker cables were provided by Anker at no cost to me. Because of this I tried to stay away from writing a purely subjective review and have attempted to provide scientific evidence that is demonstrative of the products quality.

 

]]>
http://www.gearandtechblog.com/2015/11/10/usb-cables-does-premium-equal-better/feed/ 0
Sending programmatic HTML Email with Spring + Thymeleaf + MyBatis + Database Templates http://www.gearandtechblog.com/2015/06/24/sending-programmatic-html-email-with-spring-thymeleaf-mybatis-database-templates/ http://www.gearandtechblog.com/2015/06/24/sending-programmatic-html-email-with-spring-thymeleaf-mybatis-database-templates/#respond Thu, 25 Jun 2015 05:35:08 +0000 http://www.gearandtechblog.com/?p=390 This bit of code came out of a project I worked on for an application team that doesn’t have a Java developer, the goal was to create an email system that can be triggered based on database rows inserted by Mainframe COBOL code. The application reads a table and looks for a record telling it which email template to use, the database row also tells it some details about what information to include. That portion of the process is beyond the scope of this post, really this was the easy part of this process.

Because the app team that will own this application does not have a dedicated developer I wanted to create something that would be fairly easy for them to maintain without making Java code changes. I wanted them to be able to update the email templates without rebuilding the WAR file and going through the deployment process. I chose to store the email templates in the DB2 database, for the templates I used a VARCHAR field with a 32KB length. 32KB may not seem like much but the thymeleaf templates are amazingly compact. The most complex email report I have written weighs in at about 7200 bytes. Please note that in this case these are internal application status type emails so they don’t need to be flashy, they have the bare minimum of CSS and formatting. You may choose to have more complex templates.

The application I wrote also has a series of screens to allow the app team to edit the HTML templates, preview the templates, and control the process that sends the emails. I wont include any details on these parts as they should be very straight forward for you. I will speak to the guts of this process which includes sending email from Spring, using Thymeleaf HTML templates and creating a custom thymeleaf view resolver to access the templates stored in the database. I also use annotated MyBatis interfaces to simplify database access.

Dependencies

This pom.xml should be good enough for a working version.

<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.package.name</groupId>
	<artifactId>yourApplicationName</artifactId>
	<packaging>war</packaging>
	<version>1.0.0-SNAPSHOT</version>
	<name>yourApplicationName</name>
	
	<!--I highly recommend you use the Spring BOM (Bill of Materials)-->
	<dependencyManagement>
	    <dependencies>
	        <dependency>
	            <groupId>org.springframework</groupId>
	            <artifactId>spring-framework-bom</artifactId>
	            <version>4.1.6.RELEASE</version>
	            <type>pom</type>
	            <scope>import</scope>
	        </dependency>
	    </dependencies>
	</dependencyManagement>
	<dependencies>
		<!--Dependancies for your average spring mvc application, not all will be needed-->
		<!-- Spring framework -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
		</dependency>
		<!-- Log4J -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.12</version>
		</dependency>
		<!-- Thymeleaf -->
		<dependency>
			<groupId>org.thymeleaf</groupId>
			<artifactId>thymeleaf-spring4</artifactId>
			<version>2.1.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.thymeleaf.extras</groupId>
			<artifactId>thymeleaf-extras-springsecurity4</artifactId>
			<version>2.1.2.RELEASE</version>
		</dependency>
	        <!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.2.8</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>javax.mail-api</artifactId>
			<version>1.5.3</version>
		</dependency>
		<dependency>
		  <groupId>com.sun.mail</groupId>
		  <artifactId>javax.mail</artifactId>
		  <version>1.5.3</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>yourAppName</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.3</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

 

Spring namespace configuration

applicationContext

In this context we will define the following,

  • Component scan path
  • SMTP connection using Springs JavaMailSenderImpl
  • Custom thymeleaf view resolver for access views stored on the database. We define this here so classes not annotated as @Controller can access them.
  • MyBatis configuration

<?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:jdbc="http://www.springframework.org/schema/jdbc" xmlns:lang="http://www.springframework.org/schema/lang"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
	xmlns:util="http://www.springframework.org/schema/util" xmlns:cache="http://www.springframework.org/schema/cache"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context	http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/jdbc		http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
		http://www.springframework.org/schema/lang		http://www.springframework.org/schema/lang/spring-lang.xsd
		http://www.springframework.org/schema/util		http://www.springframework.org/schema/util/spring-util.xsd
		http://www.springframework.org/schema/cache		http://www.springframework.org/schema/cache/spring-cache.xsd
		http://www.springframework.org/schema/tx		http://www.springframework.org/schema/tx/spring-tx.xsd
		http://www.springframework.org/schema/jee		http://www.springframework.org/schema/jee/spring-jee.xsd
		http://www.springframework.org/schema/task		http://www.springframework.org/schema/task/spring-task.xsd
		http://www.springframework.org/schema/task		http://www.springframework.org/schema/task/spring-task.xsd
		http://www.springframework.org/schema/mvc		http://www.springframework.org/schema/mvc/spring-mvc.xsd"
	default-lazy-init="false">

	<context:component-scan base-package="com.testapp" />
	
	<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
		<property name="host" value="smtp.hostname.com" />
		<property name="port" value="25" />
		<property name="protocol" value="smtp" />
		<property name="javaMailProperties">
		<props> <!-- properties can be found here http://edelstein.pebbles.cs.cmu.edu/jadeite/main.php?api=javamail&state=package&package=com.sun.mail.smtp -->
                	<prop key="mail.transport.protocol">smtp</prop>
                	<prop key="mail.smtp.auth">false</prop>
                	<prop key="mail.smtp.starttls.enable">false</prop>
                	<prop key="mail.smtp.ehlo">false</prop> <!-- may be true in your application-->
                	<prop key="mail.debug">true</prop>
		</props>
		</property>
	</bean>
	
	<!--  THYMELEAF-SPECIFIC ARTIFACTS                                    -->
	<!--  TemplateEngine <- TemplateResolver <- ViewResolver              -->	
	
	<!-- Email Templates stored in DB2 EMAIL_TEXT table, this is defined here so classes not annotated as controller can make use of it -->
	<bean id="db2TemplateResolver" class="com.testapp.thymeleaf.DbTemplateResolver">
		<property name="order" value="1"/>
		<property name="cacheable" value="false" />
	</bean>
	
	<bean id="emailTemplateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
		<property name="templateResolvers">
			<set>
				<ref bean="dbTemplateResolver"/>
			</set>
		</property>
 	</bean>
   
	<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
		<property name="templateEngine" ref="emailTemplateEngine" />
	</bean>
	
	<!-- Class path scanner for mybatis annotated interfaces-->
	<!-- Scan only packages named .dao because mybatis will pickup ANY interface even non mybatis interfaces-->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.testapp.dao" />
	</bean>
	
	<jee:jndi-lookup id="defaultDataSource"
		jndi-name="jdbc/myAppDb"
		resource-ref="true"
		cache="true"
		expected-type="javax.sql.DataSource" 
	/>
	
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" lazy-init="false">
		<property name="dataSource" ref="defaultDataSource" />
	</bean>
	
</beans>

servletContext

Here we will define the following,

  • Annotation driven MVC
  • Component scan for @Controller only this prevents objects from being picked up twice, I think I had to do this because proxies where being registered twice and it was affecting my EHCACHE implementation. You may not need this filtering.
  • Custom database template resolver, this allows us to preview the templates in the browser
  • Standard template resolver for pages

<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc
                           http://www.springframework.org/schema/mvc/spring-mvc.xsd
                           http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">
    
  <!--  SPRING ANNOTATION PROCESSING                                    -->
	<mvc:annotation-driven />
	
	<context:component-scan base-package="com.testapp" use-default-filters="false">
  		      <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>  
	</context:component-scan>
	
  <!--  THYMELEAF-SPECIFIC ARTIFACTS                                    -->
  <!--  TemplateEngine <- TemplateResolver <- ViewResolver              -->
  
	<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
		<property name="prefix" value="/WEB-INF/templates/" />
		<property name="suffix" value=".html" />
		<property name="templateMode" value="HTML5" />
		<property name="cacheable" value="false" />
		<property name="order" value="1"/>
	</bean>
	
	<!-- Email Templates stored in DB2 table -->
	<!-- This tempate resolver is defined in the servlet context so users can preview the emails in the browser-->
	<bean id="dbTemplateResolver" class="com.testapp.thymeleaf.DbTemplateResolver">
		<property name="order" value="2"/>
		<property name="cacheable" value="false" />
	</bean>
	
	<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
		<property name="templateResolvers">
			<set>
				<ref bean="templateResolver"/>
				<ref bean="dbTemplateResolver"/>
			</set>
		</property>
 	</bean>
   
	<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
		<property name="templateEngine" ref="templateEngine" />
	</bean>

	<mvc:resources mapping="/css/**" 		location="/resources/static/css/" />
	<mvc:resources mapping="/fonts/**" 		location="/resources/static/fonts/" />
	<mvc:resources mapping="/images/**" 		location="/resources/static/images/" />
	<mvc:resources mapping="/scripts/**" 		location="/resources/static/scripts/" />
</beans>

Database Table

Your table can be as simple as 3 columns

  1. email_type – ID column PK
  2. email_subject – Subject line for the email
  3. email_text – large text field for the html content

Custom Template Resolver and Resource Resolver

Here we will extend the Template Resolver and implement the IResourceResolver

  • Define a prefix so that we can call this resolver specifically, in my case I used the db2: prefix
  • Override the getResourceAsStream method
    • Use DAO to get template from the database as a String object
    • Turn the String object into a ByteArrayInputStream object and return it to the caller

package com.testapp.thymeleaf;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.thymeleaf.TemplateProcessingParameters;
import org.thymeleaf.resourceresolver.IResourceResolver;
import org.thymeleaf.templateresolver.TemplateResolver;

import com.testapp.beans.EmailText;
import com.testapp.dao.MailDAO;

public class DbTemplateResolver extends TemplateResolver {
	
	private final static String PREFIX = "db2:";
	
	private static final Logger log = Logger.getLogger(DbTemplateResolver.class);
	
	@Autowired
	SendmailDAO dao;
	
	
    public DbTemplateResolver() {
        setResourceResolver(new DbResourceResolver());
        Set<String> p = new HashSet<String>();
        p.add(PREFIX + "*");
        setResolvablePatterns(p);
    }
    
    @Override
    protected String computeResourceName(TemplateProcessingParameters params) {
        String templateName = params.getTemplateName();
        String retVal = templateName.substring(PREFIX.length());
        log.debug("Template Resource Name: " + retVal);
        return retVal;
    }
    
    private class DbResourceResolver implements IResourceResolver {

        @Override
        public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
        	
        	EmailText template;
			try {
				template = dao.selectTemplateByType(resourceName);
	        	if(template == null){
	        		log.error("Template not found for resourceName: " + resourceName);
	        	}
	        	log.trace("Template: " + template);
	        	
	            if (template != null && !template.getEmailText().isEmpty()) {
	                return new ByteArrayInputStream(template.getEmailText().getBytes());
	            }	
			} catch (Exception e) {
				log.error(e);
			}
            return null;
        }

        @Override
        public String getName() {
            return "dbResourceResolver";
        }
    }
}

EmailText bean

Straight forward bean

package com.testapp.beans;

import org.apache.commons.lang3.builder.ToStringBuilder;

public class EmailText {
	
	private String emailType;
	private String emailSubject;
	private String emailText;
		
	public String getEmailType() {
		return emailType;
	}

	public void setEmailType(String emailType) {
		this.emailType = emailType.trim();
	}

	public String getEmailSubject() {
		return emailSubject;
	}

	public void setEmailSubject(String emailSubject) {
		this.emailSubject = emailSubject.trim();
	}

	public String getEmailText() {
		return emailText;
	}

	public void setEmailText(String emailText) {
		this.emailText = emailText.trim();
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}

}

MyBatis DAO Interface

Simple interface to query the database for the template and return an EmailText object.

package com.testapp.dao;

import java.util.List;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.cache.annotation.Cacheable;

import com.testapp.beans.EmailText;


public interface TemplateDAO {

	final String SQL_SELECT_ET_BY_TYPE = 	"SELECT * FROM EMAIL_TEXT WHERE EMAIL_TYPE = #{emailType}";
	
	@Select(SQL_SELECT_ET_BY_TYPE)
	@Results({
		@Result(column="EMAIL_TYPE",		property="emailType"),
		@Result(column="EMAIL_SUBJECT",		property="emailSubject"),
		@Result(column="EMAIL_TEXT",		property="emailText")
	})
	public EmailText selectTemplateByType(String emailType) throws Exception;
}

Email Service

This service accept the following arguments on the sendEmail method

  • viewName, this is the EMAIL_TYPE column on the database
  • recipientEmail, String Array containing the email addresses the mail will go to
  • data, object of any type. Type doesn’t matter because thymeleaf will use reflection to get the data. This is exactly the same as the object you would load into the model when serving a template in an spring mvc environment. I choose to always load it into the context under the name emailDataObject. Field names must comply with the java bean standards.

In this class we will do the following,

  • Create a thymeleaf Context and load the embeded .jpg logo (if needed) and the emailDataObject
  • Retrieve the html template from the database through a MyBatis DAO interface
  • Build mime message using the Spring JavaMailSender bean
  • Render the HTML content using Thymeleaf Template Engine
  • Get the logo.jpg from the class path and add it as an inline image. In my webapp I kept the .jsp in /src/main/resources

You can think of this class the same way as you would think of a @Controller and its supporting @Services. Here you will gather all of the data needed to render the HTML but instead of sending the HTML to the client (as in Spring MVC) you are putting it into an email. Replace the ModelMap object of a spring controller with the org.thymeleaf.context.Context object.

package com.testapp;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.mail.internet.MimeMessage;

import org.apache.log4j.Logger;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;

import com.testapp.EmailText;
import com.testapp.dao.TemplateDAO;

@Service
public class EailService {
	
	private static final Logger log = Logger.getLogger(EailService.class);
	
	//org.springframework.mail.javamail.JavaMailSenderImpl bean defined in applicationContext.xml
	@Autowired
	JavaMailSender mailSender;
	
	//org.thymeleaf.spring4.SpringTemplateEngine bean defined in applicationContext.xml	
	@Autowired
	SpringTemplateEngine templateEngine; 
	
	@Autowired
	TemplateDAO dao;
	
	public String sendEmail(final String viewName, final String[] recipientEmail, Object data, boolean debug) throws Exception {
		log.debug("ViewName: " + viewName);		 
		
		//Prepare the evaluation context
		final Context ctx = new Context();
		ctx.setVariable("imageResourceName", "logo.jpg"); //Set file name so it can be referenced from html
		ctx.setVariable("emailDataObject", data);
		  
		EmailText et = dao.selectTemplateByType(viewName);
		
		if(et == null){
			throw new RuntimeException("Null value returned when selecting EMAIL_TYPE: " + viewName);
		}
		 
		// Prepare message using a Spring helper
		final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
		final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart
		message.setSubject(et.getEmailSubject());
		message.setFrom(getDefaultAddress());
		message.setTo(recipientEmail);
		 
		// Create the HTML body using Thymeleaf
		final String htmlContent = this.templateEngine.process("db2:" + viewName, ctx);

		message.setText(htmlContent, true); // true = isHtml
		 
		// Add the inline image, referenced from the HTML code as "cid:${imageResourceName}"
		byte[] image = getLogo("/logo.jpg");
		if(image != null){
			message.addInline("logo.jpg", new ByteArrayResource(image), "image/jpeg");
		}
		// Send mail
		this.mailSender.send(mimeMessage);
		return "Message sent";
	}

	public byte[] getLogo(String fileName){
		byte[] image;
		try {
			InputStream is = this.getClass().getResourceAsStream(fileName);
			image = IOUtils.toByteArray(is);
		} catch (IOException e) {
			log.error(e);
			return null;
		}
		return image;
	}
}

EmailData bean

Simple bean for this example. Make it as complex as you need. I am assuming you know how to work with Thymeleaf already.

package com.testapp.beans;

import org.apache.commons.lang3.builder.ToStringBuilder;

public class EmailData {
	
	private String text = "HTML email created with Spring, Thymeleaf, and MyBatis!";
		
	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text.trim();
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}
}

Template

This is a super simple template with one field. Notice how the logo is referenced.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<style>
		<!--define some CSS here if need be-->
	</style>
</head>
<body>
	<img src="cid:logo.jpg"/><br/><br/>
	<h3 th:text="${emailDataObject.text"></h3>
</body>
</html>

Reference

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/

http://www.thymeleaf.org/

http://mybatis.github.io/mybatis-3/

]]>
http://www.gearandtechblog.com/2015/06/24/sending-programmatic-html-email-with-spring-thymeleaf-mybatis-database-templates/feed/ 0
Under Cabinet Lighting http://www.gearandtechblog.com/2015/06/24/under-cabinet-lighting/ http://www.gearandtechblog.com/2015/06/24/under-cabinet-lighting/#respond Thu, 25 Jun 2015 02:41:07 +0000 http://www.gearandtechblog.com/?p=379 Adding under cabinet lighting is an excellent functional upgrade for your kitchen. My configuration may not work for your particular situation but hopefully this post will give you ideas.

 

Running the wires takes a little planning, if you have high quality cabinets it will be a little more difficult because its unlikely you will have gaps and hidden spaces to run wires. For the time being my house has off the shelf big box cabinets that have plenty of spaces for wires and I don’t feel too bad about drilling holes in them. Please note that you should only run low voltage wires in this manner.

DSC00545-sm

 

I ran the wires down the gap between two cabinets. The wires are routed through plastic wire channel available at any big box home store, the switch and surface mount box can be found in the same department. Note that I am switching the low voltage 12VDC not line voltage. In this photo you can see the LED puck lights, there are 3x 1Watt LED’s in each light, they are rated at 240 lumens per fixture. These lights as listed as Warm White, I estimate the color temperature at about 3000k, they are slightly cooler than the 2700k LED retrofits in the ceiling.

DSC00548-sm

 

If you don’t have space for a surface mount switch you can use a remote controlled switch such as this.

DSC00551-sm

 

You will need a decent quality “LED Driver” which is really nothing more than a transformer that will turn your line voltage (120VAC) into 12VDC. If you need dimming functionality you will have to take several factors into consideration. Some LED fixtures such as the LED pucks I choose include a bridge diode (bridge rectifier), these types of fixtures are identifiable by the fact that they are not sensitive to polarity. Any non-bridged LED will be sensitive to polarity. Because of this bridge these LED’s will not dim with a PWM dimmer. If your LED’s do not have a bridge you can dim them with a $5 PWM controller. The best way to dim a bridged LED fixture is to use a magnetic transformer and a dimmer switch on the line voltage side of the circuit. Size your transformer based on the current draw of your lights. I chose the 80 watt transformer because I will likely add a LED strand on top of the cabinets as accent lighting.

I wired the low voltage side into a fuse block for easy distribution. I put the transformer into the cabinet above the microwave since I never put anything in there. Even though I have the under cabinet switch I also used one of the RF controlled outlets so I can control the lights with a remote.

DSC00544-sm

 

On the low voltage side I used a bus topology that is run across the entire width of the cabinets. Each light then has a small wire (about 22ga) that is then soldered onto the bus. Between cabinets I drilled holes and pushed the wires through. I chose 14ga wire though I should have used a 12ga minimum because I’m getting about a .5v drop by the end of the 14ft run. I should have done the math on this but I figured at 3.5 amps the 14ga would have been sufficient. I had to stop here for the time being because I ran out of puck lights, another pack of 10 are in the mail so I can do the other side of the kitchen. These particular puck lights are also available in daylight at 6000k.

DSC00550-sm

 

Detail on the plastic wire conduit. Its a 1″ width. If I had to do it again I would go the next size up, it starts to get very tight inside when including the plastic connectors that come pre-installed on the puck lights. I cut them to width using a stanley miter box.

DSC00549-sm

 

*UPDATE*

I added a LED strip above the cabinets as accent lighting, turned out pretty good. The above cabinet lights + under cabinet are drawing 72 watts and provide more than enough light to work by.

image1-sm

Link to the strip and remote control

LED Strip on Amazon

RF LED controller

Parts list for my install.


]]>
http://www.gearandtechblog.com/2015/06/24/under-cabinet-lighting/feed/ 0
The joys of buying a house! http://www.gearandtechblog.com/2014/10/15/the-joys-of-buying-a-house/ http://www.gearandtechblog.com/2014/10/15/the-joys-of-buying-a-house/#respond Wed, 15 Oct 2014 23:06:54 +0000 http://www.gearandtechblog.com/?p=372 Sorry I havent posted in a while, I ended up buying a house and have been insanely busy for the past couple months. Part of the “Fun” in buying a house is fixing things. Some of those things include stuff that just makes you shake your head and ask WHY!?

In the master bath there is a 2 gallon storage type water heater under the sink. Since the bathroom is a good distance from the water heater I figured this is a pretty good idea. Until I started looking at the way it was setup. On every storage water heater (not sure about on demand types) there is a relief valve which keeps the unit from building excessive pressure and exploding if the thermostat was to malfunction and overheat the water. Normally this valve is plumbed to dump the hot water outside or into a drain, I noticed this line just went through the bottom of the vanity and the floor into the crawl space so I figured I would go under the house and figure out where it ended up.

When I got under the house I noticed the HVAC flex vent for the bathroom was sagging pretty bad, I figured it was just sagging because they only used 1 piece of webbing to support it. I grabbed the duct, thats when I noticed it was full of water! The dumbasses who installed the water heater had just stuck the end of the drain tube into the vent under the vanity!!! I stuck my trusty benchmade into the duct and water poured out!

 

IMG_2709

IMG_2710

 

Luckily there was a peak in the duct that prevented the water from pooling further back into the system and destroying a sizeable length of 14″ trunk. But it would figure that it would happen in some 5″ ducting that no one seems to stock in my area. It took two weeks to get new duct shipped in from Home Depot.

I was able to resolve the drain issue by plumbing it into a piece of pipe that is intended for a dishwasher discharge. Its technically still not correct but better than it was. It looks like the next project will be replacing the scary plastic lines under the sinks with some nice stainless braid. I am wondering if it would be a good idea to move the heater into the crawl space, not sure if its insulated enough to be outside of the conditioned space.

IMG_2728

 

 

 

]]>
http://www.gearandtechblog.com/2014/10/15/the-joys-of-buying-a-house/feed/ 0
Wet Shaving http://www.gearandtechblog.com/2014/07/16/wet-shaving/ http://www.gearandtechblog.com/2014/07/16/wet-shaving/#respond Thu, 17 Jul 2014 05:03:27 +0000 http://www.gearandtechblog.com/?p=308 I am someone who hated shaving, I was a once a month shaver for quite a few years and at best a weekly shaver since high school. Shaving was not something I enjoyed, that changed about 10 days ago when I bought a Van Der Hagen Men’s Luxury Shave Set at Wal-Mart. They also had a Van Der Hagen Safety Razor that came with a pack of blades. Now this purchase wasn’t entirely on impulse. Some of the guys on a local car message board I read had started a thread about getting started with straight razors, I was not at all interested in that. However one guy posted a link to a great blog posting How to shave like your grandpa that planted a seed in my mind. When I saw this kit in the store I had to have it.

Shave set from Wal-Mart

Shave set from Wal-Mart

I have since found quite a few other shaving blogs with a wealth of information. I will share my 3 favorites with you,

 

About the Van Der Hagen Shave Set

I found that the glycerin soap didn’t seem to work well with my skin, perhaps its my lathering technique that was failing but it didn’t seem to provide enough protection and my face was pretty irritated for the first couple of shaves. That doesn’t mean it won’t work for you, everyone is different. Its a shame because this soap smells amazing, I wish they made a cologne with this scent. The included mug seems like its of pretty good quality, its easy to hold onto. No complaints there. The Wal-Mart set seems to come with a lower quality boar hair brush. It looks like the set on Amazon.com comes with the higher quality badger brush. Its my understanding that badger hair is the way to go as its softer and holds more water.

To counter the water holding shortcoming of boar I stick my brush in a mug of warm water before getting in the shower. By the time I get out its well saturated and after a few shakes to clear the excess, holds just enough water for a great lather. I also fill the sink with about 2″ of warm water and set the mug in that, this will warm the mug so your lather is nice and warm when you apply it to your face. Shaving after a shower is an odd concept to me though logically it makes sense, the warm water will help to soften your beard and make it easier to cut. The plastic brush/razor stand is no frills acrylic but does what its intended to do.

Brush and razor in the included stand.

Brush and razor in the included stand.

Brush and lather

Brush and lather

 

The Van Der Hagen safety razor and Double Edge (DE) blades

The Van Der Hagen Safety Razor is a butterfly type meaning that unscrewing the end of the handle opens up the razor in a manner similar to bomb bay doors on a military aircraft. The alternative is a 2 or 3 piece razor where the top unscrews and lifts out of the handle. I don’t know enough to say if one design has an advantage over the other. The razor seems to be of decent quality, the nickle finish seems consistent across the entire razor with no noticeable light spots.

DSC00221-sm

About 2 days ago I noticed a flaw in this razor, the blade protrusion is greater on one side than the other. I noticed this because the shave felt different depending on which side I was using, one side was noticeably more aggressive. That said, now that I am 10 days in I seem to be able to get a great shave. I switch between the two sides and don’t favor either. As a beginner would I buy this razor again? YES, It is at least half the cost of a higher end razor. If you aren’t sure this is for you by all means buy the Van Der Hagen, its a great razor the price. Will I likely replace it in the future with a Merkur? YES. But for no other reason than I tend to like upgrades LOL!

Looking back the included blades are probably a little aggressive for a beginner. I think they are on the sharp end of the spectrum for blades and WILL irritate your skin when you are first starting. Check out the article on choosing a blade at Shaving101.com. Blades are something that are a personal choice, what works for person A wont work for person B. Its generally recommended that newbies pick up a Blade Sampler
to find out what works for them.

Proraso and blade sampler from Amazon.com

Proraso and blade sampler from Amazon.com

Shaving Cream

Since I couldn’t seem to get a lather that would protect my face with the included glycerin puck I ended up ordering some Proraso Eucalyptus & Menthol Shaving Cream. This stuff is amazing, it doesn’t smell as good as the Van Der Hagen soap but it feels great and protects very well. The menthol and eucalyptus give you a nice cooling/tingling effect.

Proraso comes in 4 types, each available as a soap (tub) or cream (tube)

  • Green – “Refreshing and Toning, suitable for all beard types.”
  • Red – “Soothing and Nourishing, suitable for thick and course beards. Sandalwood scent”
  • White – “Prevents Razor Burn, suitable for sensitive skin that tends to irritate easily. Fresh fruity scent”
  • Blue – “Protective and Moisturizing, suitable for anyone wanting a close and comfortable shave. A modern fragrance with scents of fern and spicy base notes of amber and musk.”

I think I will also end up trying the RED since my beard is very thick in the goatee area, but oddly not anywhere else.

 

If you are interested in Wet Shaving please do some reading and determine if its something you really want to do. It is not a process that can be rushed, plan on taking 10-15 min for a good shave, if you dont have time to do it properly then don’t. Rushing will only lead to pain. Amazingly even though Wet Shaving takes exponentially more effort than my previous shaving routine I must say I thoroughly enjoy it, its almost like a meditation time where nothing else matters. Its hard to explain why its enjoyable. As I learn and develop a good technique I will add more postings on the subject. Thank you for reading!

 

 

]]>
http://www.gearandtechblog.com/2014/07/16/wet-shaving/feed/ 0
Adding og (open graph) meta tags to your WordPress blog http://www.gearandtechblog.com/2014/07/12/adding-og-open-graph-meta-tags-to-your-blog/ http://www.gearandtechblog.com/2014/07/12/adding-og-open-graph-meta-tags-to-your-blog/#respond Sat, 12 Jul 2014 18:06:05 +0000 http://www.gearandtechblog.com/?p=299 Getting into blogging has had a pretty good learning curve. Getting it all to integrate with facebook has been trying at times.

I recently found out about og or Open Graph meta tags, these tags provide key information to facebook (and possibly search engines?). By default WordPress does not include this data so I did a quick search and found the “Fix Facebook Like” plugin. I installed the plugin, filled in the information required in the settings and viewed a page to validate the tags where being inserted. Bam, it worked.

meta-tags

So I fired up the Facebook Debugger to ensure everything was working. The :image tag this plugin provides tells facebook which image to use as the thumbnail. This is important because by default facebook is horrible at resolving the correct image to use when you share a link. Thats when I noticed the warning that the image specified was too small and that it would default to the next available image.

Facebook Warning

Facebook Warning

I was bummed… After some googling I couldn’t find an easy fix so I decided to take a look at the plugin code. I located the code block that gets the image URL, after searching for the method names I found the following information.

get_post_thumbnail_id
the_post_thumbnail
add_image_size

From this I determined that you can add an argument to the get_post_thumbnail_id method to retrieve the thumbnail of a given size. So I added “, ‘medium'” to the method arguments and it worked!!! I checked out the page source and it was listing the 300×200 image. A victory dance ensued. After the jovialities subsided I once again fired up the Facebook Debugger and bam, no more warnings!

This is a cut-n-paste of the code block changed.

if ( is_single() || is_page() ) {
	if ( function_exists( 'has_post_thumbnail' ) ) { // compatibility with themes who doesn't support featured thumbnails
		if ( has_post_thumbnail( $posts[0]->ID ) ) {
			$thumb = wp_get_attachment_image_src( get_post_thumbnail_id( $posts[0]->ID), 'medium' ); //<-Change made here!
			$thumb = $thumb[0]; // take the URL from the array
			$thumb_set = true;
		}
	}
}

This was all accomplished through the plugins > installed plugins > fix facebook like > edit page.

If you have any questions on getting this working for your blog feel free to hit the comments section and I will try to reply ASAP.

]]>
http://www.gearandtechblog.com/2014/07/12/adding-og-open-graph-meta-tags-to-your-blog/feed/ 0
Direct Comparison JetBoil Zip and $8 Amazon backpack stove plus GSI Halulite Kettle http://www.gearandtechblog.com/2014/07/12/direct-comparison-jetboil-zip-and-8-amazon-backpack-stove-plus-gsi-halulite-kettle/ http://www.gearandtechblog.com/2014/07/12/direct-comparison-jetboil-zip-and-8-amazon-backpack-stove-plus-gsi-halulite-kettle/#respond Sat, 12 Jul 2014 15:04:00 +0000 http://www.gearandtechblog.com/?p=288 Both of these stoves have performed without fail, they both seem to do the job in the same amount of time.

So I am giving you the data side by side so you can make a decision based on what is important to you. Obviously there are probably a hundred backpacking stoves to choose from, some will be much higher quality than those listed here, some lower. These would both be considered budget options, the cheapest JetBoil and the cheapest stove on Amazon.com.

The two contenders.

The two contenders.

Individual reviews can be seen here
JetBoil
Amazon Stove

Specifications
  JetBoil Zip Amazon $8 Stove
Street price $69.00 $31.40
Combo Weight w/o gas 363g 284g
Combo Weight w/ gas 560g 480g
Energy output (kW) 1.26 3.5
Energy output (BTU/hr) 4300 11942
As tested fuel consumption 100g consumed in 41.8 minutes 100g consumed in 12 minutes
Pack volume 88.66 Cubic Inches 91.89 Cubic Inches
Graduated Markings 4oz increments (8-16oz) 100mL increments (200-500mL) None
Advertised capacity 800mL 1 quart (32 ounces)
Runtime to boil 8 ounces 1:10 1:10
Fuel consumed per ounce boiled .4g 1.04g

Its clear that the heat exchanger setup that JetBoil has employed gives it a huge advantage. Allowing it to boil the water just as quickly as the much more powerful Amazon stove. This will however work the other way when cold so use of the plastic cup on the bottom of the pot is recommended to help keep things warm. As you can see from the data in the table above, the Amazon stove outputs twice the heat (11,942 BTU/hr vs. 4300 BTU/hr) as the JetBoil Zip. In my tests it also uses more than twice the fuel. The Amazon stoves low initial cost will soon be offset by its higher cost of ownership.


]]>
http://www.gearandtechblog.com/2014/07/12/direct-comparison-jetboil-zip-and-8-amazon-backpack-stove-plus-gsi-halulite-kettle/feed/ 0
Review: $8 Amazon backpack stove and GSI Halulite Kettle http://www.gearandtechblog.com/2014/07/10/review-8-amazon-backpack-stove-and-gsi-halulite-kettle/ http://www.gearandtechblog.com/2014/07/10/review-8-amazon-backpack-stove-and-gsi-halulite-kettle/#respond Thu, 10 Jul 2014 21:20:09 +0000 http://www.gearandtechblog.com/?p=274 This review is of the first backpacking stove I purchased a couple years back. I got it off amazon for about $8 and paired it with a $22 GSI aluminum kettle. This $30 combo has proved effective and reliable over the past 2 years or so, it has only recently been replaced by a JetBoil Zip for no other reason than I thought the JetBoil setup is “neat”.

Specifications
Street price $31.40
Combo Weight w/o gas 284g
Combo Weight w/ gas 480g
Energy output (kW) 3.5
Energy output (BTU/hr) 11942
As tested fuel consumption 100g consumed in 12 minutes
Pack volume 91.89 Cubic Inches
Graduated Markings None
Advertised capacity 1 quart (32 ounces)
Instructions (pdf) N/A

The kettle is made by GSI out of “Halulite”. GSI claims the Halulite aluminum allow is as light as titanium but conducts heat better and more evenly. It sports a hard anodized finish that resists scratches. The lid handle and bale are coated in a silicone like material that does a pretty good job at insulating your hands from the heat. The lid is very secure, if not a little hard to get off without burning your self. The detent that keeps the bale upright is a bit stiff but has loosened up some with use.

The stove doesn’t have a brand name, I assume its made in china and is probably a copy of a brand name stove. It has some pretty good reviews on Amazon. Overall I think its an amazing stove for the price, its very light and compact. It was not built to exacting standards, the pot supports don’t all touch the pot (see pictures below) but amazingly its pretty darn stable even with the full 32 ounce kettle sitting on it. A great upgrade would be to get a JetBoil canister foot. The output is pretty impressive at almost 12,000 BTU. I have noticed that the flame is stronger to one side but when boiling water that doesn’t seem to matter much. If you are using a frying pan you may want to keep an eye out for hot spots.

In my tests I was able to boil 16 ounces of water in around 2:45 seconds with an air temp of 65 degrees. It did 8 ounces in about 1:10 in the same air temp. I did not get a time for a full 32 ounce kettle.

The theoretical fuel consumption should be 100g of fuel (6615 BTU) in 33.23 minutes. This would suggest that a small 100g canister should be able to boil 16 ounces around 12 times for a total of 6 quarts.

As tested fuel consumption was lower, I boiled a total of 24 ounces in my tests (about 3 min total burn time) and the stove consumed 25g of fuel. That gives us a burn rate of 7.2 seconds per gram of fuel. That suggests a full 100g canister should be consumed in 12 minutes, that would give us the capability to boil 16 ounces about 4.3 times. Admittedly that doesn’t sound right but its what the numbers show. There is liquid fuel lost every time you attach and detach the stove from the canister so I am sure that plays into this number. If you are not quick with the canister change you will loose more fuel. However, this stove does put out a ton of heat (11942 BTU) which does equate to fuel consumption.

Fuel canister weight

  • Before Test: 196g
  • After Test: 171g

Despite the fuel consumption if you are looking into getting into backpacking and don’t want to invest a ton of money into your kit this is the way to go. The stove has been reliable and the price cant be beat. The kettle is great and can even be used on a regular stove, I keep it in my RV because of its low weight compared to traditional stove top kettles. In my opinion a bug out bag is not complete without this $8 stove and a couple of gas canisters.

Bottom Line
Pros

  • Low cost combination
  • Reliable function
  • Kettle holds a lot of water, you could make an MRE and still have enough hot water for coffee
  • Stove has built in piezo ignitor that has functioned flawlessly

Cons

  • As tested fuel economy is low
  • No graduated markings in kettle means you must use another vessel for measuring
  • Stoves pot supports are all different heights
  • Flame is stronger to one side
  • More susceptible to wind than a Jet Boil

Amazingly stable considering the supports don't all touch

Amazingly stable considering the supports don’t all touch


The supports almost all touch

The supports almost all touch


Get in your home! Stove and 100g canister fit perfectly.

Get in your home! Stove and 100g canister fit perfectly.


Stove folded up

Stove folded up


Unfolded

Unfolded


DSC00206-sm


]]>
http://www.gearandtechblog.com/2014/07/10/review-8-amazon-backpack-stove-and-gsi-halulite-kettle/feed/ 0
Review: JetBoil Zip Cooking System http://www.gearandtechblog.com/2014/07/09/review-jetboil-zip-cooking-system/ http://www.gearandtechblog.com/2014/07/09/review-jetboil-zip-cooking-system/#respond Thu, 10 Jul 2014 05:00:28 +0000 http://www.gearandtechblog.com/?p=256 For my bugout bag/day pack I choose the smallest of the Jet Boil systems, the Zip. This size should be perfect size for a single person and adequate for two people seeing as most MRE type meals only require 8 ounces of water.

Specifications
Street price ~$69.00
Weight w/o gas 363g
Weight w/ gas 560g
Energy output (kW) 1.26
Energy output (BTU/hr) 4300
As tested fuel consumption 100g consumed in 41.8 minutes
Pack volume 88.66 Cubic Inches
Graduated Markings 4oz increments (8-16oz) 100mL increments (200-500mL)
Advertised capacity 800mL
Instructions (pdf) Click Here

 

The insulation works very well, there is a double thick section opposite from the carry handle that makes it very comfortable to handle even with boiling water. I did find that that it was easy to get the pot to boil over when boiling 16 ounces. During handling the lid seems like it would never stay attached when pouring and seems to come off very easily, in practice I haven’t had it come off when pouring but I am not sure I would trust it enough to use the strainer side. The plastic cup attached to the bottom serves two potential purposes, the first would be to insulate the heat exchanger when sitting, the second would be to act as a cup/measuring cup. It holds 8 ounces with graduated markings at 4oz, 8oz and 100mL, 200mL. The markings are very faint and almost unusable.

In a couple of tests I found it will boil 16 ounces in about 2min 45sec with an ambient air temperature of around 65 degrees. Boil times seemed to be unaffected by altitude as the 16 ounce boils where done at 10,400 FT (2:47) and 6300 FT (2:45), this is likely due to different boiling temps at different pressures. In order to determine fuel level in a partially used canister I weigh my gas canisters when new, the canister I used for the tests weighed in at 197g without the plastic cap. During my tests I boiled a total of 40 ounces of water (1x 8ounce, 2x 16ounce). The canister after the tests weighed in at 181g meaning it consumed 16g of fuel, total burn time 402 seconds. (25.125 seconds to burn 1g fuel). Assuming this data stays consistent across the entire life of the canister we can surmise that it will burn through a 100g canister in 41.875 minutes. So you should be able to boil 16 ounces around 15.22 times for a total of 243 ounces or 7.18L, considerably less than the 12L specified by Jet Boil.

  • 16 ounce burns = 2:45, 2:47
  • 8 ounce burn = 1:10

The theoretical burn time is a lot longer, according to the Jet Boil manual (linked above in spec table) JetBoil 1g of fuel generates 66.15BTU though some of their math doesn’t add up. This would mean at a consumption rate of 4300 BTU/hr a 100g canister (6615 BTU) would be consumed in 1.54 hours. That would suggest you could boil 16 ounces 33.6 times, for a total of  537 ounces or 15.89L. The real world numbers I recorded are likely lower due to the gas loss from connecting/disconnecting the canister for 3 cooking sessions. If you are in a situation where gas consumption is life and death you may consider not detaching the canister after use.

 

Bottom line

Pros

  • Fuel efficient
  • Wind resistant
  • light weight
  • Good insulation makes it comfortable to hold when hot
  • Very stable with plastic canister foot

Cons

  • Poor graduated markings in plastic cup
  • Easily boils over with 16 ounces
  • No integrated ignitor
  • Silicone lid seems insecure (though I haven’t had it come off when pouring liquid)
Ready for stowage

Ready for stowage

Assembled unit

Assembled unit

Diagram I use often to remember how to put it back together.

Diagram I use often to remember how to put it back together.

Nesting storage

Nesting storage

Graduated marking detail

Graduated marking detail

Lid detail with pour spout and strainer.

Lid detail with pour spout and strainer.

Say "ahhh"

Say “ahhh”

Heat exchanger detail

Heat exchanger detail

Heat exchanger detail

Heat exchanger detail

Burner detail

Burner detail

Go knob

Go knob

Measure your canisters when full so its easy to determine the fuel level with partial canisters.

Measure your canisters when full so its easy to determine the fuel level with partial canisters.


]]>
http://www.gearandtechblog.com/2014/07/09/review-jetboil-zip-cooking-system/feed/ 0
Pictures from camping trip to Show Low AZ July 2014 http://www.gearandtechblog.com/2014/07/07/pictures-from-camping-trip-to-show-low-az-july-2014/ http://www.gearandtechblog.com/2014/07/07/pictures-from-camping-trip-to-show-low-az-july-2014/#respond Tue, 08 Jul 2014 03:59:24 +0000 http://www.gearandtechblog.com/?p=175 I spent a week camping at Fool Hollow state park in Show Low Arizona. Good times were had by all!

[See image gallery at www.gearandtechblog.com]

]]>
http://www.gearandtechblog.com/2014/07/07/pictures-from-camping-trip-to-show-low-az-july-2014/feed/ 0