Friday, October 30, 2015

Java Applets Don't Run In Chrome Browser


Have you noticed that some web pages have previously dynamic sections that no longer work in Chrome?

Have you seen a message stating, "Chrome no longer supports NPAPI"?

That's because the Chrome Browser no longer supports java applets... and for good reason: Running java applets in your Chrome browser is a security risk.

Options for the Die Hards

If you are determined to run that web page with that non-functional java applet, regardless of it's security implications, you have options:

Run Java Applets By

  • Using a browser that still supports NPAPI (MS IE, Safari, Firefox)
  • Use the IE Tab plugin for Chrome (for Windows platform)
  • Convert Java Applet to a Web Start application (if you can influence development)

NPAPI

Google's Chrome version 45 (scheduled for release in September 2015) drops support for NPAPI, impacting plugins for Silverlight, Java, Facebook Video and other similar NPAPI based plugins.

Netscape Plugin Application Programming Interface (NPAPI) is an application programming interface (API) that allow plug-ins (more specifically, browser extensions) to be developed for web browsers.

It was first developed for Netscape browsers, starting in 1995 with Netscape Navigator 2.0, but was subsequently adopted by other browsers.

In NPAPI architecture, a plugin declares content types (e.g. "audio/mp3") it can handle. When the browser encounters a content type it cannot handle natively, it loads the appropriate plugin, sets aside space within the browser context for the plugin to render and then streams data to it. The plugin is responsible for rendering the data. The plugin runs in-place within the page, as opposed to older browsers that had to launch an external application to handle unknown content types.

NPAPI requires each plugin to implement and expose approximately 15 functions for initializing, creating, destroying and positioning plugin content. NPAPI also supports scripting, printing, full-screen plugins, windowless plugins and content streaming.

Full privileges are only granted by default to chrome scripts.

Mozilla

Mozilla is deprecating all plugins.

"Plugins are now a legacy technology. They are not available on most mobile devices. Mozilla encourages website developers to avoid using plugins wherever possible. If there are plugin features which are not available in the web platform, we encourage developers to post their use cases to mozilla.dev.platform project list, so that Mozilla can prioritize web platform work to make those use cases possible."

Note that plugins are shared libraries that users can install to display content that the application itself can't display natively. For example, the Adobe Reader plugin lets the user open PDF files directly inside the browser, and the QuickTime and RealPlayer plugins are used to play special format videos in a web page.

Furthermore...


If you developed a java applet for a web page and deployed it to production, you might want to keep fact that off your resume.

Running java in a web browser was never a good idea.

The java applet is executed within a bloated Java Virtual Machine (JVM) in a process separate from the web browser itself. The java plugin was designed to run the java applets in a "secure sandbox" in the browser. This would supposedly prevent any java applet from presenting security risks to your computer.

The reality is that there have been so many vulnerabilities that allow nefarious Java applet code to escape the sandbox and exploit your system that Oracle has basically given up.

Java will no longer run unsigned applets, unless you go to the trouble of reducing your browser's default security settings. Running unsigned applets shouldn’t be a problem if the security sandbox were trustworthy in the first place. Right?

Furthermore, the graphics generated from Java apps, IMHO, never were crisp and/or visually appealing.

Cisco’s 2014 annual security report claims that 91 percent of all web attacks in 2013 targeted Java.

Running java applets in a browser will be insecure, slow, have high resource requirements and look sub-par; So, don't do it.

References



This work is licensed under the Creative Commons Attribution 3.0 Unported License.

Wednesday, October 28, 2015

The Hand-Crafted SQL Anti Pattern

You probably should have used an ORM if...

  • your app has a lot of SQL statements that exceed 200 lines
  • you use multiple CTE (WITH Clauses) to deal with the complexity of your looong SQL statements
  • you frequently implement helper functions that return SQL clauses
  • you frequently refactor your helper functions that return SQL clauses
  • you find it takes more time to add functionality to your SQL queries than it took to design the database DDL, indexes and write that super long SQL in the first place

Those are a few indications of deeper issues.

Before you discount the "exceed 200 lines" or "multiple CTE" items, please consider that the reason for having sql helper clauses is typically to reduce the complexity of the sql statement; If the sql statement needs simplification then odds are it's too darn long; Hence, the "exceeds 200 lines" and "multiple CTE" remarks.

Another rule of thumb of mine... If any logic (any language) exceeds 150 lines long, it's probably too long and should probably be refactored.

Technical Debt

With a lot of hard coded SQL, you'll likely encounter problems down the road like...

SQL Errors you might get with Pagination


In this case, we were using a WITH clause and wanted to enforce a new sorting order...


ERROR:  SELECT DISTINCT ON expressions must match initial ORDER BY expressions
LINE 52: select distinct on (s.id)
                             ^
********** Error **********

ERROR: SELECT DISTINCT ON expressions must match initial ORDER BY expressions
SQL state: 42P10
Character: 1213

We learn by ERROR that when we try to add the flexibility of changing the sort order, we have new, unforeseen problems to solve which are a direct result of our legacy, hard-coded SQL.

Reasons to use a lot of hard-coded SQL, instead of an ORM...

  • Your business objects are not easy to map to database tables
  • Your application needs lot of complex, hand-tuned SQL
  • You use a lot of stored procedures and complex logic in your database

If this is your case, you should probably revisit your database design and Data Manipulation Language (DML) implementation strategies and actively reduce your technical debt before you are asked to maintain all that hard-coded SQL.

Intelligent enterprise application design begins with information architecture and a solid database design.

If you frequently feel that it takes a lot longer to add functionality to your application than it should, you should closely examine your application architecture.

Disclaimer

Q: Am I saying that you should always use an ORM to solve your all of your DML needs?

A: No.

However, I am saying that if the vast majority of your DML code is hard-coded SQL, you should probably find a good ORM that fits in your technology stack and learn how to use it.

References

None. That's just my hard-knock experience speaking.

This work is licensed under the Creative Commons Attribution 3.0 Unported License.

Sunday, October 25, 2015

Handling Errors in Go


Using Golang best practices for handling errors, we handle the error ASAP if it's not nil.

This avoids nested blocks of logic and is generally a good idea in any language.

Frequently, we want to return an error message in the form of a formatted string.

First Try

This technique requires both fmt and error packages to be imported.


   err = db.Select(&customer, "SELECT * FROM customer WHERE id = ?", 999)
   if err != nil {
      err = errors.New(fmt.Sprintf("Unable to process customer: %v [Error: %+v]", id, err))
      return
   }

Better - Use fmt.Errorf

  • Fewer imports (only requires fmt)
  • Fewer function calls
  • Less code


   err = db.Select(&customer, "SELECT * FROM customer WHERE id = ?", 999)
   if err != nil {
      err = fmt.Errorf("Unable to process customer: %v [Error: %+v]", id, err)
      return
   }

Generally speaking...

  • the fewer packages you include, the less there is to break now and in the future
  • the fewer function calls you make, the faster your code is going to run
  • the less code you have, the less code you have to review, compile and maintain

Okay, But Can Do Even Better?

Granted, we've simplified our code, but if we use the New function from the errors package to create package level, exported defined error variables we can return those to a caller that can compare them.

Define Errors

Define errors in customer package:


ErrCustomerNotFound := errors.New("customer: id not found")
ErrTimeout := errors.New("customer: timeout")

Compare Error


response, err := processCustomer()
if err != nil {
    switch err {
    case customer.ErrCustomerNotFound:
        // Handle customer not found error.
        return
    case customer.ErrTimeout:
        // Handle timeout error.
        return
    default:
        // General error handler
        return
    }
}

Return Error Interface Type

It is idiomatic in Go to use the error interface type as the return type for any error that is going to be returned from a function or method.

This interface is used by all the functions and methods in the standard library that return errors.

For example, here is the declaration for the Get method from the http package:


http://golang.org/pkg/net/http/#Client.Get

func (c *Client) Get(url string) (resp *Response, err error)


Since we have defined our err return argument in our function definition, we can use a simple return command and our err value will be returned through the error interface type definition.

Even Better

Go's design encourages us to explicitly check for errors where they occur; Contrast this with other languages that encourage throwing exceptions and sometimes catching them.

However, this can lead to a lot of error handling code.

How can we reduce our code and add features, like adding an error code, that can be leveraged to support I18N requirements?

If we have one service handler which is the only place that handles processCustomer calls, we can return a service-specific error object.


type svcError struct {
    Code    int
    Error   error
}


The code can be used to lookup the appropriate, localized message and the original error can be passed along to the handler.


func processCustomer(req *svc.Request, resp svc.Response) *svcError {    
    if custID, err := req.Get("id"); err != nil {
        return &svcError{CustomerIdNotFound, err}
    }
    return nil
}


It helps to define error code constants.

const CustomerIdNotFound = 10001

Improvements


  • Allow svcError to take a slice of parameters that can be used to construct a more complicated error message
  • Include a StackTrace
  • Handle panics in svcError and report a more user friendly message to the consumer




References


This work is licensed under the Creative Commons Attribution 3.0 Unported License.

Sunday, October 11, 2015

The NoSQL Big Data Face Palm

I have found in practice that the use of NoSQL databases to solve Big Data problems largely exist where there was an architect that (pick one or more):
  • Thought a NoSQL technology could provide reliable, believable and accessible data that everyone in the corporation can rely on
  • Wanted to try a new technology and did not foresee the technical debt that would accrue overtime where strong schema enforcement is not baked into the database solution
  • Was more interested in a quick win with a promising technology than a sustainable, long term architecture that required significant database design and forethought
  • Failed to understand when to use OLTP and when to use OLAP and how data should be modeled and how it should flow from a live system to a reporting/analytics system
  • Did not understand how to use Database Sharding to achieve high performance with distributed large data stores
  • Thought designing for ease of programming at the cost sparseness of data storage was a best practice.
  • Thought, "Disk storage is cheap.", but failed to take IO into account.
  • Thought, "We have so much data, we won't consider backup or disaster recovery".
  • Failed to account for the effects of technology churn of their new technology
  • Does this a lot:  


Disclaimer

I am not saying that technologies like Cassandra, Riak, Hadoop, MongoDB, etc., should have no place in any corporate portfolio.

(There are many use cases where the capability of storing unpredictable and/or amorphous data is a necessity, but often times there will be a relational database that contains the metadata to make sense of the noSQL data.)

I am saying that implementations and deployments of those technologies have caused a lot of data integrity issues and should be thoughtfully considered before adoption.

References



This work is licensed under the Creative Commons Attribution 3.0 Unported License.

Tuesday, October 6, 2015

El Capitan, Homebrew and Java

It's a good idea to upgrade to El Capitan.

As usual, with major updates things break.

In this post we'll look at how to get homebrew and Java functioning properly.

Java

The first thing you may notice is that any application you use, e.g., IntelliJ, that require Java does not work.

Let's fix that by updating Java for El Capitan.

Go Here and click the Download button

Java for OS X 2015-001

After the javaforosx.dmg file is downloaded into your ~/Downloads folder, just double click it from the Finder and follow all the prompts to install it.

Update Java

Next, you'll want to go to your system preferences and update Java:




Now, you can verify it and see where El Capitan puts Java:




Jenv

If you're like me and use jenv, you'll need to update that, too.

Note: jEnv is a command line tool to help you forget how to set the JAVA_HOME environment variable.

brew info jenv - Error

If you get an error like the following when attempting to run brew info...


$ brew info jenv
jenv: stable 0.4.3 (bottled), HEAD
Manage your Java environment
http://www.jenv.be
/usr/local/Cellar/jenv/20130917 (62 files, 260K) *
  Built from source
From: https://github.com/Homebrew/homebrew/blob/master/Library/Formula/jenv.rb
==> Caveats
To enable shims and autocompletion add to your profile:
  if which jenv > /dev/null; then eval "$(jenv init -)"; fi

To use Homebrew's directories rather than ~/.jenv add to your profile:
  export JENV_ROOT=/usr/local/opt/jenv
~ $ brew update
error: unable to unlink old '.travis.yml' (Permission denied)
Error: Failure while executing: git pull --ff --no-rebase --quiet origin refs/heads/master:refs/remotes/origin/master


Fix Permissions

... then you should fix the permissions in the /usr/local directory:


sudo chown $(whoami):admin /usr/local && sudo chown -R $(whoami):admin /usr/local


Note that the previous commands will fix a good number of other homebrew issues.

Update jenv shim

You'll want to update line 21 in $HOME/.jenv/shims/java

For me, I had to change this...


exec "/usr/local/Cellar/jenv/20130917/libexec/libexec/jenv" exec "$program" "$@"


...to this:


exec "/usr/local/Cellar/jenv/0.4.3/libexec/libexec/jenv" exec "$program" "$@"


Set Global jEnv Java Version

If you see this...


$ jenv versions
jenv: version `oracle64-1.6.0.65' is not installed
  system
  oracle64-1.7.0.75
  oracle64-1.8.0.31


... then, run this:


$ jenv global oracle64-1.8.0.31

$ jenv versions
  system
  oracle64-1.7.0.75
* oracle64-1.8.0.31 (set by /Users/lex/.jenv/version)


Check Java Version

Finally, you can verify that Java is now happy:


$ java -version
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)


Brew

Homebrew needs some love, too.

Just keep running brew update and doing what it says until you see this:


$ brew update
Already up-to-date.


Then, run brew doctor to be sure you're all good with brew:


$ brew doctor
Your system is ready to brew.


References

Java for OS X 2015-001 jEnv

This work is licensed under the Creative Commons Attribution 3.0 Unported License.