All posts by Mark Jacobsen

Weekly Round-Up: 3/24/13 to 3/30/13

The Weekly Round-Up is a once weekly collection of my #1Aday daily shares. Hope you find something of interest!

Mon 3/25
How car salesmen use the Four Square Worksheet to get you to pay as much as possible – thanks genius for posting 🙂 – http://markjacobsen.net/l/1760

Tue 3/26
17 Things Car Salesmen Don’t Want You to Know – http://markjacobsen.net/l/1761

Wed 3/27
Get the Best Price on Your Next Car by Never Setting Foot on the Lot Until You’re Ready to Buy – http://markjacobsen.net/l/1762

Thu 3/28
Money Might Be Ruining Your Mood (Here’s How to Stop It) – http://markjacobsen.net/l/1763

Fri 3/29
Email Best Practices for Teams – http://markjacobsen.net/l/1764

Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...

XPath Query Not Returning any Results in Java

In looking over documentation on XPath queries it seemed easy enough to be able to pull out values from XML, but try as I might I kept getting no results back. Even searching on the root element “/elementName” didn’t return any results. Of course, as with all things Java there’s a trick and that trick is to call setNamespaceAware(). Here’s a quick and dirty example…


DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(false); // NEVER FORGET THIS
DocumentBuilder builder = domFactory.newDocumentBuilder();
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("/items/item[@id='2']");
return (NodeList)expr.evaluate(domDocument, XPathConstants.NODESET);
Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...

Weekly Round-Up: 3/17/13 to 3/23/13

The Weekly Round-Up is a once weekly collection of my #1Aday daily shares. Hope you find something of interest!

Mon 3/18
Christopher S Penn @cspenn reminds us about the power of open standards asking: What will kill email? – http://markjacobsen.net/l/1754

Tue 3/19
John Cheese on: 4 Things Politicians Will Never Understand About Poor People – http://markjacobsen.net/l/1755

Wed 3/20
The @tmninja on: 10 Mistakes Companies Make That Destroy Employee Productivity – http://markjacobsen.net/l/1756

Thu 3/21
Big Food Is Making Us Sick – http://markjacobsen.net/l/1757

Fri 3/22
How I failed my daughter and a simple path to wealth – http://markjacobsen.net/l/1759

Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...

Output a DOM Document as XML using Java

Ok, here’s another nerdy post for all the java developers out there.  Hopefully it saves you some time.

Let’s say you have a XML DOM Document that you’ve been modifying in your code, and now want to write it back out as XML.  One would think there would be a nice toXml() method or something on the Document, but there isn’t.  Instead, make sure you have the xalan.jar file on your class path and use this function…


public static String getDomDocumentAsXml(org.w3c.dom.Document domDocument)
{
	try
	{
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer transformer = tf.newTransformer();
		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
		StreamResult xmlOutput = new StreamResult(new StringWriter());
		transformer.transform(new DOMSource(domDocument), xmlOutput);
		return xmlOutput.getWriter().toString();
	}
	catch (Exception e) { e.printStackTrace(); return null; }
}
Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...

Weekly Round-Up: 3/10/13 to 3/16/13

The Weekly Round-Up is a once weekly collection of my #1Aday daily shares. Hope you find something of interest!

Tue 3/12
The Pawn Shop Debacle: I learned why Pawn Shops are evil & reinforced the value of being able to fix things http://markjacobsen.net/l/1749

Wed 3/13
Christopher S. Penn @cspenn on: Which 3 metrics should you pay attention to – http://markjacobsen.net/l/1750

Thu 3/14
The @tmninja on: 10 Ways You’re Wasting Other People’s Time – http://markjacobsen.net/l/1752

Fri 3/15
100 Life Hacks That Make Life Easier – http://markjacobsen.net/l/1753

Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...

Subscribe to the newsletter if you’re reading this in Google Reader

Do you read this blog on Google Reader? Then chances are you’ve heard that the Goog is shutting the party down in July. As a big fan this makes me sad, but as the Chris(es) (Penn and Brogan) have done, I too would like to remind you that you can get the same content by subscribing via email.

When you subscribe you’ll never get more than 1 email a day (and realistically much less frequently) as well as a Weekly Round-Up of my 1 a day daily shares.

If you would rather not do that, you can follow me on the social network of your choice…

Twitter
LinkedIn
Facebook
Google+

Don’t want to do that? Hopefully you’ll bookmark the site, try another RSS Reader (maybe Feedly), or at least stop by from time to time.

Note: I’ll likely post this periodically until the final nail is in the coffin. As always, thanks for reading.

Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...

Gmail Snooze Script – We Don’t Need No Stinkin MailboxApp

I’ll admit it. I got caught up in the MailboxApp fever and watched the little counter until I could get my hands on the app. Then I did and realized I didn’t particularly care for the interface or for giving up credentials to yet another service (though I do have 2 factor authentication setup). I like the Gmail interface. I think it’s done well. And I want control. So I asked that question that every engineer asks: “How can I do this better?”. Naturally the answer was smacking me in the face. Maybe a year ago I came across a Gmail snooze script, but didn’t really take the time to understand it or tweak it to my needs. This time was different.

Below you’ll find the setup instructions that will give you MailboxApp like functionality in something you completely control and that you can use from any email client. Just attach labels or move your messages to the any of the snooze labels and let the script do the rest. Personally, I’m using the script with a Dispatch “quick action” to easily triage my inbox.

See the “Setup” instructions in the comment block at the top of the code or refer to the images below…

gdrive-create-script

gdrive-blank-project

Paste the code from below into the script

gdrive-run-function gdrive-trigger-setup

To use the functionality provided by the script just move any email to one of the snooze labels. For example, Move to –> _Z/Tonight to have the email reappear at the time you selected (default: 5pm). These are the suggested options to use, but there are more specific labels you can use for tighter control:

  • _Z/Later
  • _Z/Midnight
  • _Z/Noon
  • _Z/Tonight
  • _Z/Tomorrow
  • _Z/This Weekend
  • _Z/Next Week
  • _Z/Next Month

I hope you like it!


/*
* Author: Mark Jacobsen (http://mjg2.net/code)
*
* This is a massively modified and more powerful GMail snooze script that mirrors much of the functionality of
* the iPhone "Mailbox" app with the added benefit of not having to hand over your credentials, and being able to 
* use from any mail client (web, Android, iPhone, etc).  If you like it or have suggestions, please drop me a line
* from my blog at http://mjg2.net/code
*
* Setup:
* 1) Fill in the values below (or just use the defaults)
* 2) Run the "setup()" function using the method drop down and run arrow
* 3) Set time based triggers for:
*      moveDailySnoozes() - Daily between Midnight to 1 am
*      moveHourlySnoozes() - Every 5 minutes
*
* Changes:
* 2013-05-06  markjacobsen.net  Fixed getLabelForHour to correctly handle am/pm thanks to "benlarge"
* 2014-02-23  markjacobsen.net  Fixed moveDailySnoozes to correctly handle the current DOW thanks to "Jeff Hirsch"
* 2014-03-24  markjacobsen.net  Added additional parseInt()s to moveHourlySnoozes
*/

// =============================================================================
// Set these values according to your needs
// =============================================================================
var TIMEZONE = "America/Detroit";  // Your timezone
var TONIGHT_HOUR = 17;  // Hour (on a 24 hour clock. ex: 17=5pm) representing when something snoozed until "Tonight" should reappear
var HOURS_UNTIL_LATER = 3;  // Number of hours when something snoozed until "Later" should appear
var REAPPEAR_LABEL = "_Action";  // Full label path to apply when a message reappears in the inbox (leave blank "" to not set a label)
var REAPPEAR_UNREAD = true;  // Decide if you want to mark a thread as unread when it reappears in the inbox

// ==========================================================================================
// I wouldn't recommend changing these values but it shouldn't hurt anything if done right :)
// ==========================================================================================
var LABEL_BASE = "_Z";  // The label to create all snooze labels under (it's suggested that you don't change this)
var LABEL_BASE_DOW = LABEL_BASE + "/zDay";
var LABEL_BASE_MO = LABEL_BASE + "/zMonth";
var LABEL_BASE_TOD = LABEL_BASE + "/zTime";

// =============================================================================
// =============================================================================
// Do NOT change anything below here
// =============================================================================
// =============================================================================
var LABEL_LATER = LABEL_BASE + "/Later";
var LABEL_MIDNIGHT = LABEL_BASE + "/Midnight";
var LABEL_NOON = LABEL_BASE + "/Noon";
var LABEL_TONIGHT = LABEL_BASE + "/Tonight";
var LABEL_TOMORROW = LABEL_BASE + "/Tomorrow";
var LABEL_THIS_WEEKEND = LABEL_BASE + "/This Weekend";
var LABEL_NEXT_WEEK = LABEL_BASE + "/Next Week";
var LABEL_NEXT_MONTH = LABEL_BASE + "/Next Month";


function setup() {
  GmailApp.createLabel(LABEL_BASE);
  GmailApp.createLabel(LABEL_BASE_DOW);
  GmailApp.createLabel(LABEL_BASE_MO);
  GmailApp.createLabel(LABEL_BASE_TOD);
  GmailApp.createLabel(LABEL_NEXT_WEEK);
  GmailApp.createLabel(LABEL_NEXT_MONTH);
  GmailApp.createLabel(LABEL_LATER);
  GmailApp.createLabel(LABEL_MIDNIGHT);
  GmailApp.createLabel(LABEL_NOON);
  GmailApp.createLabel(LABEL_TONIGHT);
  GmailApp.createLabel(LABEL_TOMORROW);
  GmailApp.createLabel(LABEL_THIS_WEEKEND);
  GmailApp.createLabel(getLabelForDayOfWeek("Sunday"));
  GmailApp.createLabel(getLabelForDayOfWeek("Monday"));
  GmailApp.createLabel(getLabelForDayOfWeek("Tuesday"));
  GmailApp.createLabel(getLabelForDayOfWeek("Wednesday"));
  GmailApp.createLabel(getLabelForDayOfWeek("Thursday"));
  GmailApp.createLabel(getLabelForDayOfWeek("Friday"));
  GmailApp.createLabel(getLabelForDayOfWeek("Saturday"));
  
  // Time of day Labels
  for (var i = 0; i <= 23; ++i) {
    GmailApp.createLabel(getLabelForHour(i));
  }
  
  // Month Labels
  for (var i = 0; i <= 11; ++i) {
    GmailApp.createLabel(getLabelForMonth(i));
  }
}

function test(){
  Logger.log(getLabelForHour(0));
  Logger.log(getLabelForHour(12));
  Logger.log(getLabelForHour(13));
  Logger.log(getLabelForHour(23));
}

function getLabelForHour(hr){
  var ampm = "am";
  if (hr > 12)
  {
    hr -= 12;
    ampm = "pm";
  }
  else if (hr == 12)
  {
    ampm = "pm";
  }
  else if (hr == 0)
  {
    hr = 12;
    ampm = "am";
  }
  return LABEL_BASE_TOD + "/" + parseInt(hr) + ampm;
}

function getLabelForMonth(mo){
  var tmp;
  
  if (mo == -1){
    tmp = new Date();
  }else{
    tmp = new Date(2000, mo, 1);
  }
  return LABEL_BASE_MO + "/"  + Utilities.formatDate(tmp, TIMEZONE, "MMMMM");
}

function getLabelForDayOfWeek(dow){
  return LABEL_BASE_DOW + "/" + dow;
}


function moveDailySnoozes() {
  var dow, dom, mo;
  
  // Move anything that was snoozed until tomorrow
  moveSnoozesToInbox(LABEL_TOMORROW);
  
  dow = Utilities.formatDate(new Date(), TIMEZONE, "EEEE");
  dom = Utilities.formatDate(new Date(), TIMEZONE, "d");
  
  // Move anything that was snoozed until this DOW
  moveSnoozesToInbox(getLabelForDayOfWeek(dow));
  
  if ((dow == "Sunday") || (dow == "Saturday")){
    // If something was snoozed until this weekend, that should be moved too
    moveSnoozesToInbox(LABEL_THIS_WEEKEND);
  }
           
  // Move anything for "next week" to the DOW it should come off snooze (i.e. the current DOW).
  // This works and doesn't move the messages pre-maturely because we moved
  // msgs for the DOW, prior to this and this functions should only fire
  // once a day
  moveSnoozes(LABEL_NEXT_WEEK, getLabelForDayOfWeek(dow));
  
  if (dom == 1){
    // Move anything snoozed until "next month" or
    // specifically for the current month on the 1st day
    // of a new month
    moveSnoozesToInbox(getLabelForMonth(-1));
    moveSnoozesToInbox(LABEL_NEXT_MONTH);
  }
}

function moveHourlySnoozes() {
  var curHour, curHourLabel, hourForLater, curDateTime;
 
  curHour = Utilities.formatDate(new Date(), TIMEZONE, "H");
  curHourLabel = getLabelForHour(curHour);
  
  moveSnoozes(LABEL_NOON, getLabelForHour(12));
  moveSnoozes(LABEL_MIDNIGHT, getLabelForHour(0));
  
  if (parseInt(curHour) == parseInt(TONIGHT_HOUR)){
    moveSnoozesToInbox(LABEL_TONIGHT);
  }
  
  moveSnoozesToInbox(curHourLabel);
  
  hourForLater = parseInt(parseInt(curHour) + HOURS_UNTIL_LATER);
  if (hourForLater >= 24){
    hourForLater = parseInt(hourForLater - 24);
  }
  moveSnoozes(LABEL_LATER, getLabelForHour(hourForLater));
}


function moveSnoozesToInbox(oldLabelName) {
  var oldLabel, page, reappearLabel;
  oldLabel = GmailApp.getUserLabelByName(oldLabelName);
  page = null;
  // Get threads in "pages" of 100 at a time
  while(!page || page.length == 100) {
    page = oldLabel.getThreads(0, 100);
    if (page.length > 0) {
      GmailApp.moveThreadsToInbox(page);
      oldLabel.removeFromThreads(page);
      if (REAPPEAR_LABEL != ""){
        reappearLabel = GmailApp.getUserLabelByName(REAPPEAR_LABEL);
        reappearLabel.addToThreads(page);
      }
      if (REAPPEAR_UNREAD == true){
        GmailApp.markThreadsUnread(page);
      }
    }     
  }
}


function moveSnoozes(oldLabelName, newLabelName) {
  var oldLabel, newLabel, page;
  oldLabel = GmailApp.getUserLabelByName(oldLabelName);
  newLabel = GmailApp.getUserLabelByName(newLabelName);
  page = null;
  // Get threads in "pages" of 100 at a time
  while(!page || page.length == 100) {
    page = oldLabel.getThreads(0, 100);
    if (page.length > 0) {
      newLabel.addToThreads(page);
      oldLabel.removeFromThreads(page);
    }     
  }
}
Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...

Weekly Round-Up: 3/3/13 to 3/9/13

The Weekly Round-Up is a once weekly collection of my #1Aday daily shares. Hope you find something of interest!

Mon 3/4
Thorin Klosowski @kingthor on: How to Get Anything You Want with Minimal Negotiation – http://markjacobsen.net/l/1744

Tue 3/5
Shit Happens… to Mr. Money Mustache’s House – http://markjacobsen.net/l/1745

Wed 3/6
Been meaning to post this for a while about my favorite charity: @charitywater – http://markjacobsen.net/l/1746

Thu 3/7
Leo @zen_habits on the: Discomfort Zone: How to Master the Universe – http://markjacobsen.net/l/1747

Fri 3/8
Craig Ballantyne @craigballantyne gives you: 12 Rules to Live By – http://markjacobsen.net/l/1748

Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...

Principles, Priorities, and Values – oh my!

Lately I’ve been thinking about the important things to me. What my “principles”, “priorities”, or “values” are. I’m sure I could spout off a number of things, but here are the big ideas that come to mind.

Family
My family is the most important thing in the world to me. I will do anything within my power for my wife and kids. What is the purpose of life without someone or a cause to love?

Goals
Goals keep us moving forward. They give us something to strive for. But don’t confuse a want with a goal. Remember, goals are SMART: Specific, Measurable, Attainable, Relevant, and Time-bound.

Planning
A dream without a plan is only a wish upon a star, but beware analysis paralysis. Use planning to achieve your goals. And remember, plans change. Change with them.

Disciplined Action
This is where you walk the walk. Achieving any goal or carrying out any plan is primarily a matter of disciplined action. It’s making the hard choices. Doing things you don’t want to do. Doing as you say. Being a role-model.

Routine
The easiest way to maintain disciplined action is through routine. Routine isn’t a dirty word or meant in a negative way. Some might call it a ritual.

Spontaneity (White Space)
Of course once you have planned your disciplined actions and made them a routine it’s amazing how much time you can find for other things. Once you know where the unmovable objects are it’s easy to find the space between. Remember to keep white space in your schedule. You can’t plan everything and if you try to you will drive yourself and those around you crazy. Schedule your priorities. Don’t schedule your life.

Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...

Weekly Round-Up: 2/24/13 to 3/2/13

The Weekly Round-Up is a once weekly collection of my #1Aday daily shares. Hope you find something of interest!

Mon 2/25
Derek Khanna @dkhanna11: The Law Against Unlocking Cellphones Is Anti-Consumer, Anti-Business, & Anti-Common Sense – http://markjacobsen.net/l/1739

Tue 2/26
Joshua Fields Millburn @JFM says: Here, Have an Organ – http://markjacobsen.net/l/1740

Wed 2/27
Former sex trafficking victim shines light on dark underworld of Super Bowl – http://markjacobsen.net/l/1741

Thu 2/28
Leo @zen_habits gives: Advice to My Kids – http://markjacobsen.net/l/1742

Fri 3/1
Marelisa Fabrega @Marelisa on: The Ten Habits of Zen to Done – http://markjacobsen.net/l/1743

Please remember to subscribe to the newsletter to stay up to date!

You or someone you know looking to buy or sell?
Disclaimer: Thoughts and opinions are my own, and do not reflect the views of any employer, family member, friend, or anyone else. Some links may be affiliate links, but I don't link to anything I don't use myself. You would think this should be self evident these days, but apparently not...