Security Theater: Checking a receipt

This isn’t a technical post, just something I noticed when I was in a Sam’s club recently (if you don’t know, it’s basically CostCo).

To shop in Sam’s club (and take advantage of their super savings) you have to purchase a membership. They check your card at the register to make sure you’re a member. Makes sense, it’s their business strategy.

But then, as you’re leaving, they check you’re receipt. Consider why they do that. Here are the possibilities I can come up with:

1. Make sure you have a valid member number

Ridiculous. They already checked your card at the register. There’s no way to pay without a valid card.

2. Make sure you aren’t stealing the cart.

Also silly. The carts are oversized. The merchandise is in bulk. Unless you can teleport, shrink the cart, or decide to knock out the employee at the door, there’s no way to steal a cart full of groceries.

3. Make sure you didn’t add some items to your cart you didn’t pay for.

This one makes the most sense, but still isn’t legit. The employees don’t look through every item in your cart to know what you are leaving the store with, nor do they read your receipt fully to know what you paid for.

Conclusion: Sam’s club pays an employee to stand at the exit, and slows you down from leaving their store to put on a good show.

When a Script Becomes an Application (Sub: "What? It has to do that too?/You’re still using that?/Comeon guys, it’s not that many lines!")

I’ve posted a couple times recently about a migration project between one wiki to another and work I’ve done to create a script to move the content. I’m going to give a spoiler here: Whenever you offer to automate a part of a project and prove you
can do it, more things will get shoved into the “automate this, please” bucket.

As long as the task makes sense to automate, this is not a bad thing. It really just means that your non-programmer coworkers are starting to understand the power of programming.

“Unlimited power…of programming!”

But at some point, your simple script to automate documents moving becomes a mass of sphagetti code. It’s no longer a script, it’s a monster. And suddenly you realize you should have asked for the time to design, build, and create tests for the thing properly. Usually by this point, you’re too deep in to go back and start over. At least I am.

The script works (really well, I might add). But if someone asks for another feature or someone wants to modify it for use in another project, we’re going to have a problem. I’d like to share how I got here, and give you a few key things to watch out for to know if you’re script is becoming a monster.

At the start of the project, a simple task was described (download HTML documents and save them on a file share). Easy enough to automate.

Then, the task expanded to, “Also push them into the new wiki.” Also, not a big deal. Still pretty simple here. No red flags.

RED FLAG HERE: Because the project was in full swing when I pushed for automating the migration, there were already interns copying and pasting documents by hand. They hit a few issues with the copy and paste action and I got asked, “Could you script do a little reformating, maybe change some links, and maybe some other simple stuff?”

Watch out for these words: maybe, stuff, and simple.

None of the things they asked me to do were complicated on their own (replacing domain names in links, excluding a couple pages, only copying unique attachments, etc) but combined they made my script a monster. After hacking together a script with all of the features shoe-horned in, I was asked to do one more simple task (get a list of the attachment extensions). There was no way to work it into the current script, no easy way to exclude activities from the script, so I was done. For this new feature, I built a separate script we’ll have to run separately.

The reason to watch out for those key words is because they communicate with vagueness and leave room for things to be added and removed with little warning. If you start hearing those kinds of general, vague words or, “We’ll let you know if we need this or not”, “We’ll get you a complete list of features later” it’s important to politely communicate that if features change, you’d like some extra time to make sure the script you’re building is well designed (For this conversation, certain buzz phrases are effective and useful. Phrases like: Reusability, well engineered, software engineering life-cycle).

This is one of my longer posts, and could it be much longer still. It’s an important topic if you’re building software for a business anywhere.

Program all the things!

I’m going to walk you through a scenario that’s played out over the past couple months after I setup a Tomcat environment for a developer at our company. It’s gonna be condensed and go fast, so
brace yourself. Here we go.

Developer: Something broken. Our deploy aren’t working.
Me: Let me take a look. Have you made any changes recently?
Developer: We reinstall java, that all.
*I wind up rebuilding the entire environment and reinstalling everything*
Developer: I made environment variable change before everything broke. You change it back! Why? It no broke anything.
Me: *Face palm*

Developer: Everything broken again! We can’t deploy stuff.
Me: Did you make any changes?
Developer: They add extra processor to our VM.
*I spend a week trouble shooting*
Developer: We also delete and re-create folder inside Tomcat. But folder name is same. Shouldn’t break anything.
Me: *Face palm*

Developer: Our application no start! Tomcat broken!
Me: Everything looks fine. How do you normally start this application?
Developer: I run script.
Me: Well….that’s written in linux shell. We’re in Windows now, so you’ll need to re-write that to a windows command file.
Developer: Why?

The first two scenarious are really the point I’m trying to make, the third one was just frustrating and I’m venting. Here’s my point:

If you break something, and then go to another developer to fix it, don’t partially answer their questions. If you’re going to that person for help, you’re already admitting they have more expertise in the area than you. Half-answering their questions won’t help you save face, it will only frustrate them.

P.S. Also, I’m ready to take away this guy’s admin privileges. At this point, he’s just doing this:

Why there are no Computer Scientists in Star Trek (Seriously)

If you’ve watched any Star Trek you’ve heard all sorts of people use phrases like:

“I wrote a program to….”
“I wrote an algorithm to….”

“We designed a computer program to….”

And usually the results of their work do magical things.

What’s interesting is that EVERYONE seems to know how to write programs and make computers do anything they want. Doctors, Captains, Engineers, and even Guinan have the ability to look at source code, understand it, and modify it.

How long have computers been around? A decade tops. They’ve been common in industry for far less than that. And already if you walked into a job and said, “What’s a computer?” You’d never get hired.

This is only going to get more so as time goes on. Computer skills are going to be more and more necessary for various jobs. President Obama recognized this and commented that high schoolers should be learning how to program.

My theory: By the time we’re travelling in space, we will all be programmers. Hence no need for people who specialize in programming. Instead of going into Computer Science as a specific field, people will learn how to program for their specific field.

Or Gene Roddenberry wasn’t as perfect as we all think. But I like my first idea better.

Dot on Dot off

We can all agree that the folks over at Google are web programming wizards, right? If you’ve ever even heard of google docs and what it does with javascript, you won’t argue with me (not that you could anyways, this is a blog, not a conversation).

Now that we’re all on the same page, let’s poke fun at
google.

On my blog stats page, there’s this nifty graph:

Please take note of the cool dot that highlights where on the graph my cursor is and shows me what stats my blog has for that point in time (And yes, I’m aware almost no one reads my blog). Cool, right? I stumbled onto an error Google left in when they built this little graph. Take a look at what happens when you scroll down without moving your mouse at all.

Suddenly, our dot is off. And what if you’ve got even more space to scroll down?

Suddenly the post from blogger has stat information! Smooth, google. Real smooth.
What’s my point (besides to make fun of google a little, even though they’re all smarter than me?
Test. Test. Test. That’s my point. You can never test enough, so test as much as you possibly can.
And I found a mistake that Google made. That too.

Read the whole stacktrace/Be careful when using spring

As a disclaimer, I am critical of a lot of Spring frameworks. Don’t get me wrong, they’re often useful and can save a lot of time when they’re used right. But it’s really easy to shoot yourself in the foot (or the head) when using a lot of them. For this post, exhibit A will be Spring DI. I recently had a developer forward me the following exception:

                               org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘****************’ defined in class path resource [*****************************************************************]: Cannot resolve reference to bean ‘************************’ while setting bean property ‘senders’ with key [TypedStringValue: value [03], target type [null]]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘************************’ defined in class path resource [*****************************************************************]: Cannot resolve reference to bean ‘***********************************’ while setting bean property ‘connectionFactory’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘***********************************’: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Context: ***************/*****/***********/***************, name: jms/MQ/*****************/*******: First component in name jms/MQ/*****************/Primary not found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedMap(BeanDefinitionValueResolver.java:378)

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:161)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)

at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)

at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)

at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)

at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)

at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)

at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)

at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)

at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:384)

at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)

at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)

at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextCreated(WebApp.java:1717)

at com.ibm.ws.webcontainer.webapp.WebApp.commonInitializationFinish(WebApp.java:384)

at com.ibm.ws.webcontainer.webapp.WebAppImpl.initialize(WebAppImpl.java:299)

at com.ibm.ws.webcontainer.webapp.WebGroupImpl.addWebApplication(WebGroupImpl.java:100)

at com.ibm.ws.webcontainer.VirtualHostImpl.addWebApplication(VirtualHostImpl.java:166)

at com.ibm.ws.webcontainer.WSWebContainer.addWebApp(WSWebContainer.java:732)

at com.ibm.ws.webcontainer.WSWebContainer.addWebApplication(WSWebContainer.java:617)

at com.ibm.ws.webcontainer.component.WebContainerImpl.install(WebContainerImpl.java:376)

at com.ibm.ws.webcontainer.component.WebContainerImpl.start(WebContainerImpl.java:668)

at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:1127)

at com.ibm.ws.runtime.component.DeployedApplicationImpl.fireDeployedObjectStart(DeployedApplicationImpl.java:1319)

at com.ibm.ws.runtime.component.DeployedModuleImpl.start(DeployedModuleImpl.java:611)

at com.ibm.ws.runtime.component.ApplicationMgrImpl.startModule(ApplicationMgrImpl.java:1572)

at com.ibm.ws.runtime.component.ApplicationMgrImpl._startModule(ApplicationMgrImpl.java:1520)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)

at java.lang.reflect.Method.invoke(Method.java:611)

at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:49)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)

at java.lang.reflect.Method.invoke(Method.java:611)

at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:256)

at javax.management.modelmbean.RequiredModelMBean.invokeMethod(RequiredModelMBean.java:1085)

at javax.management.modelmbean.RequiredModelMBean.invoke(RequiredModelMBean.java:966)

at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:848)

at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:773)

at com.ibm.ws.management.AdminServiceImpl$1.run(AdminServiceImpl.java:1331)

at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)

at com.ibm.ws.management.AdminServiceImpl.invoke(AdminServiceImpl.java:1224)

at com.ibm.ws.management.application.sync.StartDeploymentTask.startDeployment(StartDeploymentTask.java:246)

at com.ibm.ws.management.application.sync.StartDeploymentTask.fineGrainUpdate(StartDeploymentTask.java:197)

at com.ibm.ws.management.application.sync.StartDeploymentTask.performTask(StartDeploymentTask.java:104)

at com.ibm.ws.management.application.sync.AppBinaryProcessor$ExpandApp.expand(AppBinaryProcessor.java:1682)

at com.ibm.ws.management.application.sync.AppBinaryProcessor.postProcessSynchronousExt(AppBinaryProcessor.java:723)

at com.ibm.ws.management.bla.sync.BLABinaryProcessor.postProcess(BLABinaryProcessor.java:575)

at com.ibm.ws.management.bla.sync.BLABinaryProcessor.onChangeCompletion(BLABinaryProcessor.java:452)

at com.ibm.ws.management.repository.FileRepository.postNotify(FileRepository.java:1916)

at com.ibm.ws.management.repository.FileRepository.update(FileRepository.java:1425)

at com.ibm.ws.management.repository.client.LocalConfigRepositoryClient.update(LocalConfigRepositoryClient.java:189)

at com.ibm.ws.sm.workspace.impl.WorkSpaceMasterRepositoryAdapter.update(WorkSpaceMasterRepositoryAdapter.java:665)

at com.ibm.ws.sm.workspace.impl.RepositoryContextImpl.update(RepositoryContextImpl.java:1954)

at com.ibm.ws.sm.workspace.impl.RepositoryContextImpl.synch(RepositoryContextImpl.java:1902)

at com.ibm.ws.sm.workspace.impl.WorkSpaceImpl.synch(WorkSpaceImpl.java:511)

at com.ibm.ws.management.configservice.ConfigServiceImpl.save(ConfigServiceImpl.java:702)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)

at java.lang.reflect.Method.invoke(Method.java:611)

at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:49)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)

at java.lang.reflect.Method.invoke(Method.java:611)

at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:256)

at javax.management.modelmbean.RequiredModelMBean.invokeMethod(RequiredModelMBean.java:1085)

at javax.management.modelmbean.RequiredModelMBean.invoke(RequiredModelMBean.java:966)

at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:848)

at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:773)

at com.ibm.ws.management.AdminServiceImpl$1.run(AdminServiceImpl.java:1331)

at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)

at com.ibm.ws.management.AdminServiceImpl.invoke(AdminServiceImpl.java:1224)

at com.ibm.ws.management.connector.AdminServiceDelegator.invoke(AdminServiceDelegator.java:181)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)

at java.lang.reflect.Method.invoke(Method.java:611)

at com.ibm.ws.management.connector.soap.SOAPConnector.invoke(SOAPConnector.java:453)

at com.ibm.ws.management.connector.soap.SOAPConnector.service(SOAPConnector.java:288)

at com.ibm.ws.management.connector.soap.SOAPConnection.handleRequest(SOAPConnection.java:65)

at com.ibm.ws.http.HttpConnection.readAndHandleRequest(HttpConnection.java:733)

at com.ibm.ws.http.HttpConnection.run(HttpConnection.java:532)

at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1646)

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘************************’ defined in class path resource [*****************************************************************]: Cannot resolve reference to bean ‘***********************************’ while setting bean property ‘connectionFactory’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘***********************************’: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Context: ***************/*****/**********/***************, name: jms/MQ/*************************: First component in name jms/MQ/******************************found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)

at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)

at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)

at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)

at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)

… 91 more

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘************************’: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Context: ************************, name: jms/MQ/************************: First component in name jms/MQ/************************ not found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)

at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)

at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)

at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)

at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)

… 101 more

Caused by: javax.naming.NameNotFoundException: Context: ************************, name: jms/MQ/RequestManagement/Primary: First component in name ************************ not found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]

at com.ibm.ws.naming.jndicos.CNContextImpl.mapNotFoundException(CNContextImpl.java:4378)

at com.ibm.ws.naming.jndicos.CNContextImpl.doLookup(CNContextImpl.java:1807)

at com.ibm.ws.naming.jndicos.CNContextImpl.doLookup(CNContextImpl.java:1762)

at com.ibm.ws.naming.jndicos.CNContextImpl.lookupExt(CNContextImpl.java:1513)

at com.ibm.ws.naming.jndicos.CNContextImpl.lookup(CNContextImpl.java:645)

at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:166)

at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:180)

at javax.naming.InitialContext.lookup(InitialContext.java:436)

at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)

at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)

at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)

at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)

at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:104)

at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)

at org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:201)

at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:187)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)

… 108 more

Caused by: org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0

at com.ibm.ws.naming.ipcos.WsnOptimizedNamingImpl.handleNameNotFound(WsnOptimizedNamingImpl.java:2519)

at com.ibm.ws.naming.ipcos.WsnOptimizedNamingImpl.getNextWsnOptimizedNamingContext(WsnOptimizedNamingImpl.java:1270)

at com.ibm.ws.naming.cosbase.WsnOptimizedNamingImplBase$3.run(WsnOptimizedNamingImplBase.java:4738)

at com.ibm.ws.naming.cosbase.WsnOptimizedNamingImplBase$3.run(WsnOptimizedNamingImplBase.java:4733)

at com.ibm.ws.naming.util.CommonHelpers.retry(CommonHelpers.java:771)

at com.ibm.ws.naming.cosbase.WsnOptimizedNamingImplBase.getTargetContext(WsnOptimizedNamingImplBase.java:4732)

at com.ibm.ws.naming.cosbase.WsnOptimizedNamingImplBase$LeafOperationData.(WsnOptimizedNamingImplBase.java:5311)

at com.ibm.ws.naming.cosbase.WsnOptimizedNamingImplBase.resolve_complete_info(WsnOptimizedNamingImplBase.java:2155)

at com.ibm.WsnOptimizedNaming._NamingContextStub.resolve_complete_info(_NamingContextStub.java:538)

at com.ibm.ws.naming.jndicos.CNContextImpl$2.run(CNContextImpl.java:2810)

at com.ibm.ws.naming.jndicos.CNContextImpl$2.run(CNContextImpl.java:2806)

at com.ibm.ws.naming.util.CommonHelpers.retry(CommonHelpers.java:771)

at com.ibm.ws.naming.jndicos.CNContextImpl.cosResolve(CNContextImpl.java:2804)

at com.ibm.ws.naming.jndicos.CNContextImpl.doLookup(CNContextImpl.java:1803)

… 124 more

I include the entire stack-trace to give you a little perspective (and to keep myself from looking like an idiot). Like most good trouble shooters, I skimmed the bottom of the trace and then looked more closely at the top three or four exceptions that got thrown. They were Spring bean related and there was something goofy about a classpath. I started to look at the classpath and buildpath for the project and actually spent a few weeks on and off trying to figure out what was going on before I noticed what should’ve jumped out at me right away: The middle of the trace.

Caused by: javax.naming.NameNotFoundException: Context: ************************, name: jms/MQ/RequestManagement/Primary: First component in name ************************ not found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]

There’s the issue, plain as day. I could’ve solved this problem in five minutes of going through WebSphere config panels and realizing that the JNDI name it was looking for didn’t exist. Instead, I ran down a bunny trail  before really examining the situation.

This story has two morals:

First, read the entire stack-trace before you start trying to figure out the problem. If you don’t want to read it all, at least skim the exceptions, especially if you notice anything that looks odd.

Second, when you’re working with Spring (or any other framework that has a tendency to throw lots of runtime exceptions) keep in mind that the framework may be an attention hog, and hiding the actual problem that you are encountering.

Programming by Word Association


A friend of mine recently told me about a conversation he had with a junior developer.

The developer was having trouble with a how a file was being read by Java. After being read by Java, the file was being parsed and used as in an HTTP post to  URL. My friend suggested he try changing the file encoding to see how it would be read.

The developer sent back his code and my friend struggled to find the changes. Finally he noticed that the developer had found a method named URLEncoder and tried to use that.

I shouldn’t need to tell you that this wasn’t the correct solution, but it highlights the need for curiosity in computer science. If  developer had a little curiosity to ask, “What’s file encoding?” Or to read the documentation for URLEncoder he would have quickly realized he wasn’t moving in the right direction.

Instead he decided to program by word association. Sometimes this strategy works, other times, it can land you in a lot of trouble.

As a programmer you should always be curious. You should always ask, “Does this actually work the way I think it does? Does it always do what I think it should do?” And always read any documentation you have available (It’s rare enough to find, you’ll eventually get excited when you do find it).

In summary, be this guy:

Security Theater: Believing Screenshots

I heard a statement today that interested me greatly. I’ll quote it directly for accuracy:

“Our auditors accept screenshots for proof of our licensing use, but not spreadsheets because spreadsheets can be manipulated.”

Now that is an interesting proposal. Let’s examine it.

No security is 100%, it is only meant to raise the level of effort required to defeat above what an attacker is willing to contribute (I’m not going to discuss whether or not believable images can be created. If you’ve used the internet in the past decade, you already know that).

The assumption our un-named auditor is making is that editing an image and making it believable is too much effort for someone to put in. Perhaps they’re right. If an attacker’s options are to buy proprietary library for $50 a year or to spend time zooming in and out in photo shop, they might pay the money.

If their options are to spend a little time in photo shop instead of buying Microsoft Office for hundreds of dollars the attacker might be willing to put a little more time and effort into the project. Let’s not mention the fact that most Enterprise level software sells for thousands or tens of thousands per year. Suddenly the hourly rate might make it worth while.

My point is that the man in picture was never going to be eaten by a shark, there are no spider-mice, and auditors should be a little more careful.

Overflowing

Do you ever have trouble learning outside of work? I certainly do. In college, during the summers, I felt like I had tons of time and concentration to dedicate to personal projects and ideas. Now, when I try to pick up a technical book outside of work, my brain stalls. Have the time, when I try to pick up a technical book at work my brain stalls. Here’s my theory. Your brain is like this:

And the water is all of the topics you’re expected to keep
track of and have ready on a moments notice when your boss or coworker asks you about them. There is no way you can actually keep track of all of these topics, some of them spill off and you need a refresher before you can talk about the intelligently.

Then, if you’re trying to learn, you’re brain does this.

Platonic Computer Science

Recently I encountered a file permissions issue. Long story short, I had a service that needed to run a .bat file, but because of a Windows quirk, it needed list access to the root of the drive the file was on. I called up my friends at our Information Security department and after getting transferred around a bit, I was informed that their policy was to not grant special access to the root of any
drive.

Rather, their preferred solution was to create a file share and grant the ID access to that, and then require the ID to reference the share through it’s UNC path name.

The computer scientist in me balked at the idea (thankfully I kept it all internal). “Are you kidding me? I’m not sure windows is smart enough to figure out the share is local, the service might wind up bouncing off of a switch or router somewhere to get to a drive on a machine it’s already on! Clearly this is not a good solution.” (It’s like typing “google” into Chrome’s awesome bar to pull up google.com and search for something).

I took some time to think about it and try to come up with a better solution (because there are better solutions out there) but then I stopped to think about it. This is a business, and the goal of every business is to make as much money as possible and spend as little as possible making it. Our information security department has a system they understand and are comfortable with and are providing a workable solution to allow my project to continue (round-a-bout as it may be). The argument, “We can’t do that! It’s….it’s…..bad!” Isn’t going to hold much water.

From a business perspective, there’s no noticable performance drain, no monetary reason not to use the solution that’s in place. It would also cost a significant number of hours to research a “better” solution and train the employees on how to implement and use it.

We computer scientists often think we are working on Platonic computer science. Computer science for computer science’s sake, make it as correct as possible just because it’s more correct. For better or worse, we don’t. We all want to get paid for what we do, and for that to happen, we need to be making the company money and not wasting more than we need to.

I’m not saying we’re going to stick with this solution, I discussed with my manager long enough to get some time to look into a more correct solution. But before you go after your business area for implementing a less correct or less technical solution, do some quick mental cost/benefit analysis of what you want to suggest and make sure it’s as good for the wallet as it is for correctness.