Showing posts with label Singleton. Show all posts
Showing posts with label Singleton. Show all posts

Tuesday, May 3, 2016

You're Killing Me Spring: "Singleton" Scope

Introduction

I generally try to avoid traditional Gang of Four Design Pattern Singletons.  In Java they are only guaranteed to be singular per running Java Virtual Machine, don't scale to a clustered environment, can be serialized / deserialized to create a duplicate even in the same JVM and are generally the OOP version of global variables.
However, in a given project I had an exception to this rule.  I had an object that was using a single TCP port going into an environment where only one instance would be deployed per machine so I thought to myself that I would use the Singleton pattern.

Background

Created at imgflip, original image copyright Dos Equis.
I have had problems with Spring before.  Specifically I was working with Spring Web Flow 3 years ago and had some configuration (including setters) in my beans.xml file, in my Spring Web Flow xml file I imported the (Singleton) beans defined in the beans.xml file.  However, instead of importing the bean it created a new instance of it, and on top of that it didn't call any of the initialization configuration in the beans.xml file leading to null pointer exceptions.  It took me three weeks to track this down.  I was working for myself (e.g. that time was on my own dime) and I ragequit Spring in favor of Google Guice.  For this project I was forced into using Spring so I had the following Hypothesis.

Hypothesis

"Verify that Spring is treating Singletons correctly because it's been unreliable, surprising and buggy in the past."  In code-form it was a standard Spring @Service in the default Singleton scope with a check in the constructor (see Further Reading for other reasons to do this) to blow up if the constructor is called twice.  In addition, Spring makes you have a public constructor even for your Singletons so blowing up can avoid programmer error of someone later trying to just call new ExampleSingleton.
@Service
// implied Spring Singleton Scope
public class ExampleSingleton {

    // should only be called once by Spring
    public ExampleSingleton() 
    {
        if (instance != null) {
            throw new IllegalStateException("Singleton constructor called twice!");
        }
    }
}    

Results

As you may have guessed from the image, Spring was attempting to create the "Singleton" repeatedly and blowing up with the IllegalStateException.  From doing some research I found that @ComponentScan was behaving strangely.  It turns out that if you have multiple Spring @Configuration classes and if they overlap on a package (e.g. @ComponentScan(basePackages = {"com.yourcompany"}) and another with @ComponentScan(basePackages = {"com.yourcompany.utils"}), Spring will (re)create all of the Singletons in the overlap (in this example com.yourcompany.utils) twice.  I found this surprising and very strange.  In addition, the same link mentions that Spring only promises that a Singleton will happen once per ApplicationContext, and Servlets usually have more than one.

Conclusion

I concluded that you can't trust Spring to honor the @Singleton contract and to manage my instances myself.  After doing more research I found that in Java the best way is to have a SingletonFactory.  I ended up having a base class called SpringSingleton, which has the documentation on why all of this is necessary and a protected constructor that keeps track of which sub-classes have been instantiated with a Set<SpringSingleton> that is accessed in a synchronized block.  In addition the @Configuration classes have an @Autowired SingletonFactory and @Bean definitions that get the beans from the SingletonFactory.  All in all it still isn't foolproof for Serializable Singletons (see below) but does a great job otherwise.  There is more complexity (4 classes for the simple case) but new Singletons end up being easy to implement and work correctly.  I would post the code but I made it at work so the company has copyright.

Too bad I couldn't just have @Component on a class with the default scope and have it work right.

Further Reading

You can abuse an enum in Java to ensure a "serializable" Singleton can't be easily duplicated but that has some drawbacks.  Given that you can invoke even a private constructor via the Java reflections API you will still want to verify that your Singletons are only being called once (or at least post a warning in the logs).

PS

There was an issue with the site CSS where black lines would appear over an image. This has been fixed.

Friday, April 5, 2013

Senior Developer Interviews: Tales from the Trenches

From my experience as a Junior Software Engineer and Java Developer, since there is such high demand for software developers as soon as you qualify for a job in the field you have a pretty good chance of landing one in short order.  Trying to go for a Senior Developer job broke the mold in a number of ways.

First off, people rise up through the pay grades for the first two levels pretty rapidly, which means that you're competing with people with approximately your experience level.  However, people with TEN years experience can be applying for a Senior Developer job.  This of course means that the required 5+ years experience is going to put your résumé not looking too hot on paper.  However, you can tell yourself that you "punch above your weight" so you'll impress them on the purely technical side.  Easier said than done as they say.

In the first two tiers, you're treated as a technical specialist.  You just have to be an expert in JavaScript OR Java OR SQL, and you're not even really expected to know in detail how those fussy clusters of computers with their web containers work in detail, that's IT's job right?  Not at the Senior level though.  You're expected to be able to prance about the entire software stack with ease and grace.  Saying that the JavaScript prototype concept is kinda like Java inheritance and leaving at that isn't going to cut it.  Confusing your jQuery with your XPath is not going to cut it.  Not knowing how to make a Java Singleton a true Singleton when deployed to a clustered environment isn't going to cut it.  Not knowing the difference between an inner and outer SQL joins isn't going to cut it.  Not knowing the details of your web containers' class loader isn't going to cut it.  On top of all of this, you're expected to have excellent soft skills at this level as well.

Just getting over social anxiety by taking a metric ton of Prozac every day is just the preliminaries of the soft skills you're going to need.  In addition to being able to charm people ("Hay!  I thought engineers were allowed to be socially awkward!"  Nope) and having the standard "Excellent Written and Verbal Communication Skills" where you thought communication skills were being able to feign interest in Steve's ukulele collection and your bosses Whole Foods shopping, veiled "spirituality" references and superstitious neo-hippy quasi-Eastern bull****, but also be able to orate and deliver technical speeches / presentations and be able to handle yourself in the office-politics charged meetings that you'll be invited to more and more. All the while keeping your code throughput high and keeping your inboxes at 0 (you also should have read Getting Things Done by now, or the context switching will require a few buckets of daily anti-psychotics as well).  Did I mention a strong social media presence and a great Klout score too?

In summary to snag that $100k+ Senior Developer job you won't just need to hone your existing skill sets, but learn many additional ones as well.  You will need to possibly hold a regular Programmer position until you have 8-10 years experience.  You will need to know the entire software stack to the point of being a quasi-superhero of computation.  Lastly you will need truly overwhelming social skills, including conducting presentations, giving prepared speeches and attending and holding meetings.  All in all, I have about 7,000 pages of books queued up to read to bring myself up to these levels, because possibly the most valuable skill you can have is being able to rise to a challenge.