tag:blogger.com,1999:blog-46366705474563889752024-03-18T01:33:35.541-07:00Crafted SoftwareAbout making quality software.Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.comBlogger149125tag:blogger.com,1999:blog-4636670547456388975.post-55500712888658811452016-08-22T18:44:00.003-07:002016-08-22T18:46:10.815-07:00Obj-C articles on (a) overview of debugging command-line, and (b) Frustrating 'block' syntaxArticles of the day for Objective-C programmers:<br />
<br />
<br />
<ul>
<li>Super useful, clear, and easy-to-read overview of options with the LLDB-based debugger command-line in Xcode 7: <a href="https://www.objc.io/issues/19-debugging/lldb-debugging/">Dancing in the Debugger — A Waltz with LLDB</a></li>
<li>After struggling with the syntax to declare a variable as an Objective-C block, and then assign the block itself, and finally pass the block variable in a method call, I began to think I was too stupid to be a programmer any longer. A DuckDuckGo search showed me the problem is with the syntax, not my brain: <a href="http://goshdarnblocksyntax.com/">GoshDarnBlockSyntax</a> (<a href="http://fuckingblocksyntax.com/">another version of the URL</a> substitutes the words "GoshDarn")</li>
</ul>
Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com4tag:blogger.com,1999:blog-4636670547456388975.post-10601586636462166812016-06-18T13:02:00.002-07:002016-08-22T18:55:14.079-07:00Quest Continues for Ultimate Programmer Font<div>
<span style="font-size: large;">San Francisco Mono</span></div>
<div>
<br /></div>
Amongst all many annoucements in <a href="https://developer.apple.com/wwdc/">WWDC 2016</a> came a new font, San Francisco Mono, called “SFmono” by some Apple folks. <a href="https://www.designernews.co/stories/67681-apple-reveals-san-francisco-monospaced-font">This discussion</a> notes that while it appears similar to <a href="https://www.google.com/fonts/specimen/Roboto">Google Roboto</a>, this font has its roots in the <a href="https://en.wikipedia.org/wiki/San_Francisco_(2014_typeface)">San Francisco font</a> family first delivered by Apple for use across its platforms. No, not that <a href="https://en.wikipedia.org/wiki/San_Francisco_(1984_typeface)">San Francisco</a>:<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://upload.wikimedia.org/wikipedia/commons/3/36/San_Francisco.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="123" src="https://upload.wikimedia.org/wikipedia/commons/3/36/San_Francisco.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<i>This</i> San Francisco:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/San_Francisco_Display_SP.svg/167px-San_Francisco_Display_SP.svg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/San_Francisco_Display_SP.svg/167px-San_Francisco_Display_SP.svg.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Colored monospaced type starred center-stage in the posters, logos, web pages, and video intros at the WWDC 2016 event.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.telegraph.co.uk/content/dam/technology/2016/06/14/Apple_WWDC_2016-xlarge_trans++QD_lvq6mq_uCaUPZ98j-IGtT0gK_6EfZT336f62EI5U.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://www.telegraph.co.uk/content/dam/technology/2016/06/14/Apple_WWDC_2016-xlarge_trans++QD_lvq6mq_uCaUPZ98j-IGtT0gK_6EfZT336f62EI5U.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Subsequently, I learned of a couple more new fonts for programmers, <i>Operator</i> and <i>CamingoCode</i>. I show these below, along with my favorite programmer fonts, <i>Menlo</i>, <i>Hack</i> and <i>Pragmata</i>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-size: large;">Operator</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="http://www.typography.com/fonts/operator/overview/">Operator</a> is a commercial font from Hoefler & Co. Operator has its own <a href="http://www.typography.com/blog/introducing-operator">story and video page</a>. Here is an interesting shot of the Atom editor configured with styling.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://cdn.typography.com/assets/images/blog/operator_ide2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="395" src="https://cdn.typography.com/assets/images/blog/operator_ide2.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<a href="https://www.myfonts.com/fonts/jan-fromm/camingo-code/">CamingoCode</a> by Jan Fromm is a commercial free-of-cost monospaced typeface designed for source-code editors. Features include “compact appearance and a moderate line height”, four styles (Regular, Italic, Bold and Bold Italic), and manual hinting.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://cdn.myfonts.net/s/aw/720x360/250/0/128283.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://cdn.myfonts.net/s/aw/720x360/250/0/128283.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-size: large;">Menlo</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Recent versions of <a href="https://en.wikipedia.org/wiki/Mac_OS">macOS</a> have seen the <a href="https://en.wikipedia.org/wiki/Menlo_(typeface)">Menlo</a> font bundled. This font is very usable for programming, certainly the best of the bundled font. Seems to be based on the <a href="http://dejavu-fonts.org/wiki/Main_Page">DejaVu Mono</a> font.</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Hack</span></div>
<div>
<br /></div>
<div>
I have enjoyed using the open-source free-of-cost font, <a href="http://sourcefoundry.org/hack/">Hack</a>. Evolved from the open-source font project <a href="https://en.wikipedia.org/wiki/DejaVu_fonts">DejaVu</a> which came from Bitstream Vera.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://sourcefoundry.org/hack/assets/img/mockup/Aa-mockup-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="468" src="https://sourcefoundry.org/hack/assets/img/mockup/Aa-mockup-2.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Pragmata</span></div>
<div>
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.fsd.it/wp-content/uploads/PragmataPro_more_working_space.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.fsd.it/wp-content/uploads/PragmataPro_more_working_space.png" height="426" width="640" /></a></div>
<br />
But the best all-time programmer font continues to be <a href="http://www.fsd.it/shop/fonts/pragmatapro/">Pragmata</a> by Fabrizio Schiavi, a commercial font. This font is distinctive for its choice to go tall rather than wide. Comes it three families, a pair of “Pro” families each with 4 styles and one with ligatures and the other without, and the “Essential” family of only two styles and limited to English for a lower-cost alternative.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br /></div>
Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com2tag:blogger.com,1999:blog-4636670547456388975.post-87987503607058365342015-09-11T13:45:00.000-07:002015-09-11T13:45:31.447-07:00Jony Ive, please, fix thisI agree with every single word of <a href="http://cheerfulsw.com/2015/destroying-apples-legacy/">this eloquent critique</a> of the seriously wrong direction taken by Apple in the user-interface design of iOS 7, 8, and 9.Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-9915916102446595132015-09-05T16:28:00.001-07:002015-09-05T16:28:05.607-07:00SQL-99 BookThe <a href="https://mariadb.com/">MariaDB.com</a> (MySQL) site provides <a href="https://mariadb.com/kb/en/sql-99/">an online version</a> of the very nice book <a href="http://www.powells.com/biblio/0879305681?&PID=33286">SQL-99 Complete, Really</a> book by <a href="http://www.amazon.com/s/ref=dp_byline_sr_book_1?ie=UTF8&text=Peter+Gulutzan&search-alias=books&field-author=Peter+Gulutzan&sort=relevancerank">Peter Gulutzan</a> & <a href="http://www.amazon.com/s/ref=dp_byline_sr_book_2?ie=UTF8&text=Trudy+Pelzer&search-alias=books&field-author=Trudy+Pelzer&sort=relevancerank">Trudy Pelzer</a>, the best SQL reference book I’ve seen. This book is based on <a href="https://en.wikipedia.org/wiki/SQL#Interoperability_and_standardization">standard SQL</a>, not specific to MySQL. Story <a href="http://monty-says.blogspot.com/2011/01/sql-99-complete-really-now-freely.html">here</a>.Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com1tag:blogger.com,1999:blog-4636670547456388975.post-14706166554082496732015-07-19T22:37:00.001-07:002015-07-19T22:46:00.027-07:00Cool MacBook WorkstationI mean <i>cool</i> literally. Apple designed the MacBook Pro laptop to run cool for basic use. But if you start pushing hard on those cores, it heats up like a hot potato. Add some ambient heat and you'll hear those little internal fans blowing a mighty wind. Electronics hate the heat, so is there a way we can make life easier for our faithful servant MacBooks?<br />
<br />
<h2>
# 1 – Roost</h2>
<br />
First step, get yourself one of the handy-dandy laptop-lifting wonders: the <a href="http://www.therooststand.com/">Roost</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBIGJG0B6IQxllFh2bGHMGaXQy-33L0RBNRfLnYnwX551o-776eEBSKGb-b-uDtHTVRCV4L39SYNkCj0u5MwZsNHVFxJMr_n3r3vqeLH7LjT5VnKKvl_erKTWb0SF3sW2tuHt1SijZHVU/s1600/roost.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="520" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBIGJG0B6IQxllFh2bGHMGaXQy-33L0RBNRfLnYnwX551o-776eEBSKGb-b-uDtHTVRCV4L39SYNkCj0u5MwZsNHVFxJMr_n3r3vqeLH7LjT5VnKKvl_erKTWb0SF3sW2tuHt1SijZHVU/s640/roost.png" width="640" /></a></div>
<br />
<br />
This clever invention is lightweight, mighty strong, easy to pack in my nifty <a href="http://www.brenthaven.com/products/prostyle-laptop-slimpack">Brenthaven SlimPack</a>, and <a href="http://cdn.shopify.com/s/files/1/0192/8184/files/Roost3.gif?14151162451162778">quick to setup/teardown</a>.<br />
<br />
I have the original <i>Roost</i>. You may have to wait to get the new design, shipping in November 2015. Hopefully better than ever, but their first design was already perfect in my mind.<br />
<br />
<h2>
# 2 – Fan</h2>
<br />
The modern MacBooks are designed to shed heat through their metal frame and casing. Move some air past that metal and you'll greatly enhance the cooling effect.<br />
<br />
So how to move air beneath your MacBook? Well, notice in that picture of the Roost how the derrière is raised upwards? Perfect positioning to place a small angled fan beneath, blowing a steady stream of air into the bottom case of your laptop. You need only a small fan, like the <a href="http://www.bestbuy.com/site/searchpage.jsp?st=mini+fan&_dyncharset=UTF-8&id=pcat17071&type=page&sc=Global&cp=1&nrp=15&sp=&qp=&list=n&iht=y&usc=All+Categories&ks=960&keys=keys">Insignia™ - High-Velocity 4" Mini Fan</a> at BestBuy.com.<br />
<br />
Cost? Six bucks on sale now. Usually USD $ 10.<br />
<br />
Available in <a href="http://www.bestbuy.com/site/insignia-high-velocity-4-mini-fan-white/1345134.p?id=1219488150868&skuId=1345134">white</a>, <a href="http://www.bestbuy.com/site/insignia-high-velocity-4-mini-fan-blue/1346019.p?id=1219488150878&skuId=1346019">blue</a>, or <a href="http://www.bestbuy.com/site/insignia-4-high-velocity-personal-fan-sorbet/5373006.p?id=1219122730256&skuId=5373006&productCategoryId=pcmcat297500050013">sorbet</a> (pink).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.insigniaproducts.com/generated/images/products/productdetail/1345134le.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.insigniaproducts.com/generated/images/products/productdetail/1345134le.jpg" /></a> </div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.insigniaproducts.com/generated/images/products/productdetail/1346019le.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.insigniaproducts.com/generated/images/products/productdetail/1346019le.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.insigniaproducts.com/generated/images/products/productdetail/5373006_ra.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.insigniaproducts.com/generated/images/products/productdetail/5373006_ra.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The cage pivots to swing the fan upwards. You can easily adjust it to hit your MacBook.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The fan does make some noise, a steady buzz, similar to the quieter versions of fans found in the old tower computers of yore. May be a tad louder than the MacBook’s own fans. The sound seems physical, apparently the moving of the blades, and much less annoying than an electronic hum. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The small motor has some unexpected heft, hopefully will prove reliable. Has a metal cage and shiny metal blades rather than crude plastic. Moves just the right amount of air to keep the MacBook cool and its internal fans off while not disturbing me or my papers.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com4tag:blogger.com,1999:blog-4636670547456388975.post-84550448036504109272015-06-18T21:57:00.000-07:002015-06-18T21:57:00.783-07:00How many SQL keywords?Collisions between your table/column names and SQL reserved keywords is easier than you might think. Much easier.<br />
<br />
Pop Quiz<br />
<br />
Here's a list of words I could easily imagine using as column names. Can you pick out which are reserved by either the SQL standard or by proprietary extensions of various database products?<br />
<span style="color: yellow;"><br />KEY<br />UNIQUE<br /><br />EXISTS<br />PLAN<br /><br />USER<br />VIEW<br />WORK<br /><br />POSITION<br />TOP<br />LEFT<br />RIGHT<br />UPPER<br /><br />OPEN<br />CLOSE<br />OUTPUT<br />FILE<br /><br />SIZE<br />ADD<br />DELETE<br />MATCH<br /><br />HOST<br />GROUP<br />EXTERNAL<br /><br /><br />STATISTICS<br />PROCEDURE<br />VALUES<br />REFERENCES<br />SCOPE<br /><br />BULK<br />NATURAL<br /><br />FOREIGN<br />PUBLIC<br />GLOBAL<br />LANGUAGE<br />MAP<br /><br />FOUND<br />HOLD<br />FREE<br /><br />ORDER<br />LINENO<br />TRANSACTION<br /><br />LOAD<br />CASE<br />SET<br />PARTIAL<br />SECTION<br />PERCENT<br /><br /><br />HOUR<br />MONTH<br />YEAR<br />DATE<br />TIME<br />CURRENT<br />ZONE</span><br /><br />Trick question. <i>All</i> of those are reserved.<br />
<br />
Some brief digging around on the Internet, found me plenty of keywords, most of them reserved or possibly causing problems if used as your own identifiers in naming tables, columns, indexes, constraints, functions, and so on.<br />
<br />
I wrote a little Java app to eliminate duplicates. How many did I find? Over a thousand! Exact total: 1,131. I would bet money you can find more. See the full list below.<br />
<br />
<h3>
Trailing Underscore </h3>
Tip: Avoid such collisions by giving all your SQL identifiers (names of columns, tables, indexes, constraints, and such) <u><b><span style="color: #ea9999;">a trailing underscore</span></b></u>.<br />
<br />
Examples: "person_", "invoice_", "date_of_birth_".<br />
<br />
The SQL standard explicitly promises to never use a trailing underscore in any name, keyword, or other SQL-related context.<br />
<br />
<h3>
List Of Reserved Keywords</h3>
The following list an intersection of these three lists:<br />
<br />
<ul>
<li><a href="http://www.tigerlogic.com/tigerlogic/omnis/download/manuals/SQLReservedWords.pdf">TigerLogic</a></li>
<li><a href="https://www.drupal.org/node/141051">Drupal</a></li>
<li><a href="http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html">Postgres</a></li>
</ul>
<span style="color: cyan;"><span style="font-family: "Courier New",Courier,monospace;">A<br />ABORT<br />ABS<br />ABSENT<br />ABSOLUTE<br />ACCESS<br />ACCORDING<br />ACOS<br />ACQUIRE<br />ACTION<br />ADA<br />ADD<br />ADMIN<br />AFTER<br />AGGREGATE<br />ALIAS<br />ALL<br />ALLOCATE<br />ALSO<br />ALTER<br />ALWAYS<br />ANALYSE<br />ANALYZE<br />AND<br />ANY<br />ARE<br />ARITH_OVERFLOW<br />ARRAY<br />ARRAY_AGG<br />ARRAY_MAX_CARDINALITY<br />AS<br />ASC<br />ASCII<br />ASENSITIVE<br />ASIN<br />ASSERTION<br />ASSIGNMENT<br />ASYMMETRIC<br />AT<br />ATAN<br />ATAN2<br />ATOMIC<br />ATTRIBUTE<br />ATTRIBUTES<br />AUDIT<br />AUTHORIZATION<br />AUTO_INCREMENT<br />AVG<br />AVG_ROW_LENGTH<br />BACKUP<br />BACKWARD<br />BASE64<br />BEFORE<br />BEGIN<br />BEGIN_FRAME<br />BEGIN_PARTITION<br />BERNOULLI<br />BETWEEN<br />BIGINT<br />BINARY<br />BIT<br />BITVAR<br />BIT_LENGTH<br />BLOB<br />BLOCKED<br />BOM<br />BOOL<br />BOOLEAN<br />BOTH<br />BREADTH<br />BREAK<br />BROWSE<br />BUFFERPOOL<br />BULK<br />BY<br />C<br />CACHE<br />CALL<br />CALLED<br />CAPTURE<br />CARDINALITY<br />CASCADE<br />CASCADED<br />CASE<br />CAST<br />CATALOG<br />CATALOG_NAME<br />CCSID<br />CEIL<br />CEILING<br />CHAIN<br />CHANGE<br />CHAR<br />CHARACTER<br />CHARACTERISTICS<br />CHARACTERS<br />CHARACTER_LENGTH<br />CHARACTER_SET_CATALOG<br />CHARACTER_SET_NAME<br />CHARACTER_SET_SCHEMA<br />CHARINDEX<br />CHAR_CONVERT<br />CHAR_LENGTH<br />CHECK<br />CHECKED<br />CHECKPOINT<br />CHECKSUM<br />CHILD<br />CHR<br />CLASS<br />CLASS_ORIGIN<br />CLOB<br />CLOSE<br />CLUSTER<br />CLUSTERED<br />COALESCE<br />COBOL<br />COLLATE<br />COLLATION<br />COLLATION d<br />COLLATION_CATALOG<br />COLLATION_NAME<br />COLLATION_SCHEMA<br />COLLECT<br />COLLECTION<br />COLUMN<br />COLUMNS<br />COLUMN_NAME<br />COMMAND_FUNCTION<br />COMMAND_FUNCTION_CODE<br />COMMENT<br />COMMENTS<br />COMMIT<br />COMMITTED<br />COMPLETION<br />COMPRESS<br />COMPUTE<br />CONCAT<br />CONCURRENTLY<br />CONDITION<br />CONDITION_NUMBER<br />CONFIGURATION<br />CONFIRM<br />CONNECT<br />CONNECTION<br />CONNECTIONS<br />CONNECTION_NAME<br />CONSTRAINT<br />CONSTRAINTS<br />CONSTRAINT_CATALOG<br />CONSTRAINT_NAME<br />CONSTRAINT_SCHEMA<br />CONSTRUCTOR<br />CONTAINS<br />CONTAINSTABLE<br />CONTENT<br />CONTINUE<br />CONTROL<br />CONTROLROW<br />CONVERSION<br />CONVERT<br />COPY<br />CORR<br />CORRESPONDING<br />COS<br />COST<br />COUNT<br />COVAR_POP<br />COVAR_SAMP<br />CREATE<br />CREATEDB<br />CREATEROLE<br />CREATEUSER<br />CROSS<br />CSV<br />CUBE<br />CUME_DIST<br />CURRENT<br />CURRENT_CATALOG<br />CURRENT_DATE<br />CURRENT_DEFAULT_TRANSFORM_GROUP<br />CURRENT_PATH<br />CURRENT_ROLE<br />CURRENT_ROW<br />CURRENT_SCHEMA<br />CURRENT_SERVER<br />CURRENT_TIME<br />CURRENT_TIMESTAMP<br />CURRENT_TIMEZONE<br />CURRENT_TRANSFORM_GROUP_FOR_TYPE<br />CURRENT_USER<br />CURSOR<br />CURSOR_NAME<br />CYCLE<br />DAT<br />DATA<br />DATA-PGS<br />DATABASE<br />DATABASES<br />DATALINK<br />DATE<br />DATETIME<br />DATETIME_INTERVAL_CODE<br />DATETIME_INTERVAL_PRECISION<br />DAY<br />DAYOFMONTH<br />DAYOFWEEK<br />DAYOFYEAR<br />DAYS<br />DAY_HOUR<br />DAY_MICROSECOND<br />DAY_MINUTE<br />DAY_SECOND<br />DB<br />DBA<br />DBCC<br />DBSPACE<br />DEALLOCATE<br />DEC<br />DECIMAL<br />DECLARE<br />DEFAULT<br />DEFAULTS<br />DEFERRABLE<br />DEFERRED<br />DEFINED<br />DEFINER<br />DEGREE<br />DELAYED<br />DELAY_KEY_WRITE<br />DELETE<br />DELIMITER<br />DELIMITERS<br />DENSE_RANK<br />DENY<br />DEPTH<br />DEREF<br />DERIVED<br />DESC<br />DESCRIBE<br />DESCRIPTOR<br />DESTROY<br />DESTRUCTOR<br />DETERMINISTIC<br />DIAGNOSTICS<br />DICTIONARY<br />DIM<br />DISABLE<br />DISCARD<br />DISCONNECT<br />DISK<br />DISPATCH<br />DISTINCT<br />DISTINCTROW<br />DISTRIBUTED<br />DIV<br />DLNEWCOPY<br />DLPREVIOUSCOPY<br />DLURLCOMPLETE<br />DLURLCOMPLETEONLY<br />DLURLCOMPLETEWRITE<br />DLURLPATH<br />DLURLPATHONLY<br />DLURLPATHWRITE<br />DLURLSCHEME<br />DLURLSERVER<br />DLVALUE<br />DO<br />DOCUMENT<br />DOMAIN<br />DOUBLE<br />DROP<br />DTCY<br />DTD<br />DTM<br />DTW<br />DTY<br />DUAL<br />DUMMY<br />DUMP<br />DYNAMIC<br />DYNAMIC_FUNCTION<br />DYNAMIC_FUNCTION_CODE<br />EACH<br />EDITPROC<br />ELEMENT<br />ELSE<br />ELSEIF<br />EMPTY<br />ENABLE<br />ENCLOSED<br />ENCODING<br />ENCRYPTED<br />END<br />END-EXEC<br />ENDTRAN<br />END_FRAME<br />END_PARTITION<br />ENFORCED<br />ENUM<br />EQUALS<br />ERASE<br />ERRLEVEL<br />ERRLVL<br />ERROREXIT<br />ESCAPE<br />ESCAPED<br />EVENT<br />EVERY<br />EXCEPT<br />EXCEPTION<br />EXCLUDE<br />EXCLUDING<br />EXCLUSIVE<br />EXEC<br />EXECUTE<br />EXISTING<br />EXISTS<br />EXIT<br />EXP<br />EXPLAIN<br />EXPRESSION<br />EXTENSION<br />EXTERNAL<br />EXTRACT<br />FALSE<br />FAMILY<br />FETCH<br />FIELDPROC<br />FIELDS<br />FILE<br />FILLFACTOR<br />FILTER<br />FINAL<br />FIRST<br />FIRST_VALUE<br />FLAG<br />FLOAT<br />FLOAT4<br />FLOAT8<br />FLOAT_TYPE<br />FLOOR<br />FLUSH<br />FOLLOWING<br />FOR<br />FORCE<br />FOREIGN<br />FORTRAN<br />FORWARD<br />FOUND<br />FRAME_ROW<br />FREE<br />FREETEXT<br />FREETEXTTABLE<br />FREEZE<br />FROM<br />FS<br />FULL<br />FULLTEXT<br />FUNCTION<br />FUNCTIONS<br />FUSION<br />G<br />GENERAL<br />GENERATED<br />GET<br />GLOBAL<br />GO<br />GOTO<br />GRANT<br />GRANTED<br />GRANTS<br />GRAPHIC<br />GREATEST<br />GROUP<br />GROUPING<br />GROUPS<br />HANDLER<br />HAVING<br />HEADER<br />HEAP<br />HEX<br />HIERARCHY<br />HIGH_PRIORITY<br />HOLD<br />HOLDLOCK<br />HOST<br />HOSTS<br />HOUR<br />HOURS<br />HOUR_MICROSECOND<br />HOUR_MINUTE<br />HOUR_SECOND<br />ID<br />IDENTIFIED<br />IDENTITY<br />IDENTITYCOL<br />IDENTITY_INSERT<br />IF<br />IGNORE<br />ILIKE<br />IMMEDIATE<br />IMMEDIATELY<br />IMMUTABLE<br />IMPLEMENTATION<br />IMPLICIT<br />IMPORT<br />IN<br />INCLUDE<br />INCLUDING<br />INCREMENT<br />INDENT<br />INDEX<br />INDEXES<br />INDICATOR<br />INFILE<br />INFIX<br />INHERIT<br />INHERITS<br />INITCAP<br />INITIAL<br />INITIALIZE<br />INITIALLY<br />INLINE<br />INNER<br />INOUT<br />INPUT<br />INSENSITIVE<br />INSERT<br />INSERT_ID<br />INSTANCE<br />INSTANTIABLE<br />INSTEAD<br />INT<br />INT1<br />INT2<br />INT3<br />INT4<br />INT8<br />INTEGER<br />INTEGRITY<br />INTERSECT<br />INTERSECTION<br />INTERVAL<br />INTO<br />INVOKER<br />IS<br />ISAM<br />ISNULL<br />ISOLATION<br />ITERATE<br />JOIN<br />K<br />KEY<br />KEYS<br />KEY_MEMBER<br />KEY_TYPE<br />KILL<br />LABEL<br />LAG<br />LANCOMPILER<br />LANGUAGE<br />LARGE<br />LAST<br />LAST_INSERT_ID<br />LAST_VALUE<br />LATERAL<br />LC_COLLATE<br />LC_CTYPE<br />LEAD<br />LEADING<br />LEAKPROOF<br />LEAST<br />LEAVE<br />LEFT<br />LENGTH<br />LESS<br />LEVEL<br />LIBRARY<br />LIKE<br />LIKE_REGEX<br />LIMIT<br />LINENO<br />LINES<br />LINK<br />LIST<br />LISTEN<br />LN<br />LOAD<br />LOCAL<br />LOCALTIME<br />LOCALTIMESTAMP<br />LOCATION<br />LOCATOR<br />LOCK<br />LOCKSIIZE<br />LOG<br />LOG10<br />LOGIN<br />LOGS<br />LONG<br />LONGBLOB<br />LONGTEXT<br />LOOP<br />LOWER<br />LOW_PRIORITY<br />M<br />MAP<br />MAPPING<br />MATCH<br />MATCHED<br />MATERIALIZED<br />MAX<br />MAXEXTENTS<br />MAXVALUE<br />MAX_CARDINALITY<br />MAX_ROWS<br />MEDIUMBLOB<br />MEDIUMINT<br />MEDIUMTEXT<br />MEMBER<br />MERGE<br />MESSAGE_LENGTH<br />MESSAGE_OCTET_LENGTH<br />MESSAGE_TEXT<br />METHOD<br />MICROSECOND<br />MICROSECONDS<br />MIDDLEINT<br />MIN<br />MINUS<br />MINUTE<br />MINUTES<br />MINUTE_MICROSECOND<br />MINUTE_SECOND<br />MINVALUE<br />MIN_ROWS<br />MIRROR<br />MIRROREXIT<br />MLSLABEL<br />MOD<br />MODE<br />MODIFIES<br />MODIFY<br />MODULE<br />MONTH<br />MONTHNAME<br />MONTHS<br />MORE<br />MOVE<br />MULTISET<br />MUMPS<br />MYISAM<br />NAME<br />NAMED<br />NAMES<br />NAMESPACE<br />NATIONAL<br />NATURAL<br />NCHAR<br />NCLOB<br />NESTING<br />NEW<br />NEXT<br />NFC<br />NFD<br />NFKC<br />NFKD<br />NHEADER<br />NIL<br />NO<br />NOAUDIT<br />NOCHECK<br />NOCOMPRESS<br />NOCREATEDB<br />NOCREATEROLE<br />NOCREATEUSER<br />NOHOLDLOCK<br />NOINHERIT<br />NOLOGIN<br />NONCLUSTERED<br />NONE<br />NORMALIZE<br />NORMALIZED<br />NOSUPERUSER<br />NOT<br />NOTHING<br />NOTIFY<br />NOTNULL<br />NOWAIT<br />NO_WRITE_TO_BINLOG<br />NTH_VALUE<br />NTILE<br />NULL<br />NULLABLE<br />NULLIF<br />NULLS<br />NUMBER<br />NUMERIC<br />NUMERIC_TRUNCATION<br />NUMPARTS<br />OBID<br />OBJECT<br />OCCURRENCES_REGEX<br />OCTETS<br />OCTET_LENGTH<br />OF<br />OFF<br />OFFLINE<br />OFFSET<br />OFFSETS<br />OIDS<br />OLD<br />ON<br />ONCE<br />ONLINE<br />ONLY<br />OPEN<br />OPENDATASOURCE<br />OPENQUERY<br />OPENROWSET<br />OPENXML<br />OPERATION<br />OPERATOR<br />OPTIMIZE<br />OPTION<br />OPTIONALLY<br />OPTIONS<br />OR<br />ORDER<br />ORDERING<br />ORDINALITY<br />OTHERS<br />OUT<br />OUTER<br />OUTFILE<br />OUTPUT<br />OVER<br />OVERLAPS<br />OVERLAY<br />OVERRIDING<br />OWNED<br />OWNER<br />P<br />PACKAGE<br />PACK_KEYS<br />PAD<br />PAGE<br />PAGES<br />PARAMETER<br />PARAMETERS<br />PARAMETER_MODE<br />PARAMETER_NAME<br />PARAMETER_ORDINAL_POSITION<br />PARAMETER_SPECIFIC_CATALOG<br />PARAMETER_SPECIFIC_NAME<br />PARAMETER_SPECIFIC_SCHEMA<br />PARENT<br />PARSER<br />PART<br />PARTIAL<br />PARTITION<br />PASCAL<br />PASSING<br />PASSTHROUGH<br />PASSWORD<br />PATH<br />PCTFREE<br />PCTINDEX<br />PERCENT<br />PERCENTILE_CONT<br />PERCENTILE_DISC<br />PERCENT_RANK<br />PERIOD<br />PERM<br />PERMANENT<br />PERMISSION<br />PICTURE<br />PIVOT<br />PLACING<br />PLAN<br />PLANS<br />PLI<br />PORTION<br />POSITION<br />POSITION_REGEX<br />POSTFIX<br />POWER<br />PRECEDES<br />PRECEDING<br />PRECISION<br />PREFIX<br />PREORDER<br />PREPARE<br />PREPARED<br />PRESERVE<br />PRIMARY<br />PRINT<br />PRIOR<br />PRIVATE<br />PRIVILEGES<br />PROC<br />PROCEDURAL<br />PROCEDURE<br />PROCEDUREALL<br />PROCESS<br />PROCESSEXIT<br />PROCESSLIST<br />PROGRAM<br />PUBLIC<br />PUBLICALTER<br />PURGE<br />QUOTE<br />RAID0<br />RAISERROR<br />RAISERRORAND<br />RANGE<br />RANK<br />RAW<br />READ<br />READANY<br />READS<br />READTEXT<br />READTEXTAS<br />REAL<br />REASSIGN<br />RECHECK<br />RECONFIGURE<br />RECONFIGUREASC<br />RECOVERY<br />RECURSIVE<br />REF<br />REFERENCES<br />REFERENCESAUTHORIZATION<br />REFERENCING<br />REFRESH<br />REGEXP<br />REGR_AVGX<br />REGR_AVGY<br />REGR_COUNT<br />REGR_INTERCEPT<br />REGR_R2<br />REGR_SLOPE<br />REGR_SXX<br />REGR_SXY<br />REGR_SYY<br />REINDEX<br />RELATIVE<br />RELEASE<br />RELOAD<br />RENAME<br />REPEAT<br />REPEATABLE<br />REPLACE<br />REPLICA<br />REPLICATION<br />REPLICATIONBACKUP<br />REQUIRE<br />REQUIRING<br />RESERVED_PAGES<br />RESET<br />RESIGNAL<br />RESOURCE<br />RESPECT<br />RESTART<br />RESTORE<br />RESTOREBEGIN<br />RESTRICT<br />RESTRICTBETWEEN<br />RESULT<br />RETURN<br />RETURNBREAK<br />RETURNED_CARDINALITY<br />RETURNED_LENGTH<br />RETURNED_OCTET_LENGTH<br />RETURNED_SQLSTATE<br />RETURNING<br />RETURNS<br />REVERTBROWSE<br />REVOKE<br />REVOKEBULK<br />RIGHT<br />RIGHTBY<br />RLIKE<br />ROLE<br />ROLLBACK<br />ROLLBACKCASCADE<br />ROLLUP<br />ROUND<br />ROUTINE<br />ROUTINE_CATALOG<br />ROUTINE_NAME<br />ROUTINE_SCHEMA<br />ROW<br />ROWCNT<br />ROWCOUNT<br />ROWCOUNTCASE<br />ROWGUIDCOL<br />ROWGUIDCOLCHECK<br />ROWID<br />ROWLABEL<br />ROWNUM<br />ROWS<br />ROW_COUNT<br />ROW_NUMBER<br />RRN<br />RULE<br />RULECHECKPOINT<br />RUN<br />SAVE<br />SAVECLOSE<br />SAVEPOINT<br />SCALE<br />SCHEDULE<br />SCHEMA<br />SCHEMACLUSTERED<br />SCHEMAS<br />SCHEMA_NAME<br />SCOPE<br />SCOPE_CATALOG<br />SCOPE_NAME<br />SCOPE_SCHEMA<br />SCROLL<br />SEARCH<br />SECOND<br />SECONDS<br />SECOND_MICROSECOND<br />SECQTY SECTION<br />SECTION<br />SECURITY<br />SECURITYAUDITCOALESCE<br />SELECT<br />SELECTCOLLATE<br />SELECTIVE<br />SELF<br />SEMANTICKEYPHRASETABLECOLUMN<br />SEMANTICSIMILARITYDETAILSTABLECOMMIT<br />SEMANTICSIMILARITYTABLECOMPUTE<br />SENSITIVE<br />SEPARATOR<br />SEQUENCE<br />SEQUENCES<br />SEQUENCE_TYPE<br />SERIALIZABLE<br />SERVER<br />SERVER_NAME<br />SESSION<br />SESSION_USER<br />SESSION_USERCONSTRAINT<br />SET<br />SETCONTAINS<br />SETOF<br />SETS<br />SETUSER<br />SETUSERCONTAINSTABLE<br />SHARE<br />SHARED<br />SHOW<br />SHUTDOWN<br />SHUTDOWNCONTINUE<br />SIGNAL<br />SIMILAR<br />SIMPLE<br />SIN<br />SIZE<br />SMALLINT<br />SNAPSHOT<br />SOME<br />SOMECONVERT<br />SONAME<br />SOURCE<br />SPACE<br />SPATIAL<br />SPECIFIC<br />SPECIFICTYPE<br />SPECIFIC_NAME<br />SQL<br />SQLCA<br />SQLCODE<br />SQLERRM<br />SQLERROR<br />SQLEXCEPTION<br />SQLSTATE<br />SQLWARNING<br />SQL_BIG_RESULT<br />SQL_BIG_SELECTS<br />SQL_BIG_TABLES<br />SQL_CALC_FOUND_ROWS<br />SQL_LOG_OFF<br />SQL_LOG_UPDATE<br />SQL_LOW_PRIORITY_UPDATES<br />SQL_SELECT_LIMIT<br />SQL_SMALL_RESULT<br />SQL_WARNINGS<br />SQRT<br />SSL<br />STABLE<br />STANDALONE<br />START<br />STARTING<br />STATE<br />STATEMENT<br />STATIC<br />STATISTICS<br />STATISTICSCREATE<br />STATUS<br />STDDEV_POP<br />STDDEV_SAMP<br />STDIN<br />STDOUT<br />STOGROUP<br />STOPOOL<br />STORAGE<br />STRAIGHT_JOIN<br />STRICT<br />STRING<br />STRIP<br />STRIPE SUBPAGES<br />STRUCTURE<br />STYLE<br />SUBCLASS_ORIGIN<br />SUBLIST<br />SUBMULTISET<br />SUBSTR<br />SUBSTRING<br />SUBSTRING_REGEX<br />SUCCEEDS<br />SUCCESSFUL<br />SUM<br />SUPERUSER<br />SYB_IDENTITY<br />SYB_RESTREE<br />SYMMETRIC<br />SYNONYM<br />SYSDATE<br />SYSID<br />SYSTEM<br />SYSTEM_TIME<br />SYSTEM_USER<br />SYSTEM_USERCROSS<br />T<br />TABLE<br />TABLECURRENT<br />TABLES<br />TABLESAMPLE<br />TABLESAMPLECURRENT_DATE<br />TABLESPACE<br />TABLE_NAME<br />TAN<br />TEMP<br />TEMPLATE<br />TEMPORARY<br />TERMINATE<br />TERMINATED<br />TEXT<br />TEXTSIZE<br />TEXTSIZECURRENT_TIME<br />THAN<br />THEN<br />THENCURRENT_TIMESTAMP<br />TIES<br />TIME<br />TIMESTAMP<br />TIMEZONE_HOUR<br />TIMEZONE_MINUTE<br />TINYBLOB<br />TINYINT<br />TINYTEXT<br />TO<br />TOAST<br />TOCURRENT_USER<br />TOKEN<br />TOP<br />TOPCURSOR<br />TOP_LEVEL_COUNT<br />TRAILING<br />TRAN<br />TRANDATABASE<br />TRANSACTION<br />TRANSACTIONDBCC<br />TRANSACTIONS_COMMITTED<br />TRANSACTIONS_ROLLED_BACK<br />TRANSACTION_ACTIVE<br />TRANSFORM<br />TRANSFORMS<br />TRANSLATE<br />TRANSLATE_REGEX<br />TRANSLATION<br />TRANSLATION TRIGGER<br />TREAT<br />TRIGGER<br />TRIGGERDEALLOCATE<br />TRIGGER_CATALOG<br />TRIGGER_NAME<br />TRIGGER_SCHEMA<br />TRIM<br />TRIM_ARRAY<br />TRUE<br />TRUNCATE<br />TRUNCATEDECLARE<br />TRUSTED<br />TRY_CONVERTDEFAULT<br />TSEQUAL<br />TSEQUALDELETE<br />TYPE<br />TYPES<br />UESCAPE<br />UID<br />UNBOUNDED<br />UNCOMMITTED<br />UNDER<br />UNDO<br />UNENCRYPTED<br />UNION<br />UNIONDENY<br />UNIQUE<br />UNIQUEDESC<br />UNKNOWN<br />UNLINK<br />UNLISTEN<br />UNLOCK<br />UNLOGGED<br />UNNAMED<br />UNNEST<br />UNPIVOTDISK<br />UNSIGNED<br />UNTIL<br />UNTYPED<br />UPDATE<br />UPDATEDISTINCT<br />UPDATETEXT<br />UPDATETEXTDISTRIBUTED<br />UPPER<br />URI<br />USAGE<br />USE<br />USEDOUBLE<br />USED_PGS<br />USER<br />USERDROP<br />USER_DEFINED_TYPE_CATALOG<br />USER_DEFINED_TYPE_CODE<br />USER_DEFINED_TYPE_NAME<br />USER_DEFINED_TYPE_SCHEMA<br />USER_OPTION<br />USING<br />UTC_DATE<br />UTC_TIME<br />UTC_TIMESTAMP<br />VACUUM<br />VALID<br />VALIDATE<br />VALIDATOR<br />VALIDPROC<br />VALUE<br />VALUES<br />VALUESDUMP<br />VALUE_OF<br />VARBINARY<br />VARCHAR<br />VARCHAR2<br />VARCHARACTER<br />VARIABLE<br />VARIABLES<br />VARIADIC<br />VARYING<br />VARYINGELSE<br />VAR_POP<br />VAR_SAMP<br />VCAT<br />VERBOSE<br />VERSION<br />VERSIONING<br />VIEW<br />VIEWEND<br />VIEWS<br />VOLATILE<br />VOLUMES<br />WAITFOR<br />WAITFORERRLVL<br />WHEN<br />WHENESCAPE<br />WHENEVER<br />WHERE<br />WHEREEXCEPT<br />WHILE<br />WHILEEXEC<br />WHITESPACE<br />WIDTH_BUCKET<br />WINDOW<br />WITH<br />WITHEXECUTE<br />WITHIN<br />WITHIN GROUPEXISTS<br />WITHOUT<br />WORK<br />WRAPPER<br />WRITE<br />WRITETEXT<br />WRITETEXTEXIT<br />X509<br />XML<br />XMLAGG<br />XMLATTRIBUTES<br />XMLBINARY<br />XMLCAST<br />XMLCOMMENT<br />XMLCONCAT<br />XMLDECLARATION<br />XMLDOCUMENT<br />XMLELEMENT<br />XMLEXISTS<br />XMLFOREST<br />XMLITERATE<br />XMLNAMESPACES<br />XMLPARSE<br />XMLPI<br />XMLQUERY<br />XMLROOT<br />XMLSCHEMA<br />XMLSERIALIZE<br />XMLTABLE<br />XMLTEXT<br />XMLVALIDATE<br />XOR<br />YEAR<br />YEARS<br />YEAR_MONTH<br />YES<br />ZEROFILL<br />ZONE</span></span> <br />
<br />
-- fin --Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-43525990637349781602015-04-27T16:33:00.001-07:002015-04-27T16:33:42.748-07:00Tomcat MemoryModern Java supports 64-bit architectures. That means you can throw many gigs of memory at Tomcat.<br />
<div>
<br /></div>
<div>
This is especially useful in <a href="https://www.vaadin.com/">Vaadin</a> apps as the state all lives in web sessions in the Tomcat server. So those sessions tend to eat up memory.<br />
<div>
<br /></div>
<div>
My research into this topic was long and frustrating. For one thing, much discussion involves "PermGen" which is now outmoded. Current updates to Java 8 have eliminated the PermGen, so memory management is now more straightforward.</div>
</div>
<div>
<br /></div>
<div>
Eventually I learned one simple way to allocate memory to Tomcat 8. The following steps work on with the Oracle release of Java 8 on Mac OS X Mountain Lion. The steps probably work on any Unix-oriented system such as <a href="https://www.freebsd.org/">BSD</a> or Linux. Don’t know about Microsoft Windows. The "-X" flags are optional, not required by the Java spec; so other non-Oracle implementations of Java may not respect these flags.</div>
<div>
<br /></div>
<div>
<ol>
<li>Locate your Tomcat folder, and the nested the "bin" folder.</li>
<li>Create a text file named exactly "setenv.sh". </li>
<li>Add one line to the file:<br />export JAVA_OPTS="-Xms6144m -Xmx6144m"</li>
</ol>
<div>
Those two numbers should be what ever number of megs you want. So 6,144 megs is 6 gigs. I don’t know if it is required, but I would use multiples of 1024. So 6 * 1024 = 6,144.</div>
</div>
<div>
<br /></div>
<div>
By setting the minimum (<i>Xms</i>) to be the same number as the maximum (<i>Xmx</i>), Tomcat will grab and hold that entire amount of memory. If you set the minimum to be lower, you will see the amount of memory used by Tomcat grow and shrink over time as garbage collection releases memory back to the operating system. I do not know the pros and cons of these two behaviors.</div>
Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com3tag:blogger.com,1999:blog-4636670547456388975.post-57930946902031751472015-03-31T17:53:00.002-07:002015-03-31T17:53:18.483-07:00Questions About New Grid Widget In Vaadin 7.4• Can I set tooltips for the grid headers (column titles)? It is common to use abbreviations for the displayed title while wanting to show the expanded full title in a tooltip.<br />
<br />
• Similarly, can grid cell values have a tooltip? It would be nice to attach explanatory or additional info in a tooltip while keeping the displayed cell content short (abbreviated, or coded).<br />
<br />
• Does Grid slow down my app in Vaadin 7.4.2? Since I upgraded to 7.4 from 7.3, my app now displays the yellow and red spinning wheels more often.<br />
<br />
• Calling "setContainerDataSource" and passing a new container has no effect on displayed data. The documentation is sparse. Is this a bug; should setting the container cause that container's data to be displayed on screen in place of the old data? Is there some other command I am supposed to call to get the data displayed? In contrast, keeping the same container while removing all items and then adding a collection of items does indeed automatically cause the grid to display fresh data.Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-88773790968947126002015-02-28T16:26:00.001-08:002015-02-28T16:26:42.578-08:00How am I supposed to work under these conditions?!<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0XLEI71zqMFeLB6YwjaeDNnb1yYCuAcuXRNFhNajthM1468lCT8vNfryAHL7dKVA3nscAGcuGf64Y9IwYMzIEVwPiT_0LwHzZYTtsdrG8j2Mzq-Jp7XO88tyc9m7Tb5MCDF3ksbGDP-s/s1600/somafm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0XLEI71zqMFeLB6YwjaeDNnb1yYCuAcuXRNFhNajthM1468lCT8vNfryAHL7dKVA3nscAGcuGf64Y9IwYMzIEVwPiT_0LwHzZYTtsdrG8j2Mzq-Jp7XO88tyc9m7Tb5MCDF3ksbGDP-s/s1600/somafm.png" height="160" width="400" /></a></div>
<br />Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-52429677034253516372015-02-19T14:11:00.001-08:002015-02-19T14:34:38.243-08:00Helping NetBeans and Tomcat Get Along TogetherI use NetBeans 8.0.2 with Tomcat 8.0.18 for developing web apps in Vaadin 7.<br />
<br />
Generally NetBeans and Tomcat work well together. But I have learned how to workaround a pair of annoying problems.<br />
<br />
<h3>
Session Persistence</h3>
<br />
The first problem is session persistence. By default, Tomcat attempts to serialize all active sessions’ data. Serialization means extracting the data values from each session’s graph of objects and then writing those values to storage. Serializing sessions enables two uses: (a) re-create any remaining sessions when a server restarts, and (b) enable "clustering" where sessions can be moved between multiple Tomcat servers either for fail-over or for load-balancing.<br />
<br />
Those sessions’ graph of objects includes all the objects in your Vaadin app. If you fail to make all your classes serializable, then Tomcat reports errors when shutting down and/or starting up.<br />
<br />
If you don't care about (a) and (b) above, then you have no need for persistence of sessions and no need to bother making your app’s classes serializable. But how to stop Tomcat from trying and failing to persist sessions?<br />
<br />
As described at the bottom of Tomcat’s <a href="http://tomcat.apache.org/tomcat-8.0-doc/config/manager.html">Manager documentation page</a>, you can add a single line to your "context.xml" file. That file was created for you by the Vaadin plugin or Maven archetype when your project was created. In a Maven multi-module project, look within the "-ui" submodule > Web Pages > META-INF > context.xml. Change this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><?xml version="1.0" encoding="UTF-8"?></span><br />
<span style="font-family: Courier New, Courier, monospace;"><Context antiJARLocking="true" path="/MyAppName-ui"/></span><br />
<div>
<br /></div>
<div>
to this, adding a "Manager" tag:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><?xml version="1.0" encoding="UTF-8"?></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><Context antiJARLocking="true" path="/MyAppName-ui"></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> <Manager pathname="" /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"></Context></span></div>
</div>
<div>
<br /></div>
<h3>
Multi-Launching</h3>
<div>
<br /></div>
<div>
A more troublesome problem with NetBeans+Tomcat is that your Vaadin app is "double-launched". The app launches, shuts down, and launches again. At the very least this makes reading of the log confusing. Even worse, bad side-effects can happen especially if you launch daemon threads in the background. </div>
<div>
<br /></div>
<div>
Let me be clear: This is <u>only a development problem</u>, a side-effect of combining NetBeans with Tomcat. In production with Tomcat alone, no problem.</div>
<div>
<br /></div>
<div>
The cure is deletion of an XML file that represents the running of your app. Every time NetBeans finishes running your app, delete that file before running again. That file is the name of your app plus ".xml", found in the path: "conf/Catalina/localhost" within your Tomcat's "Cataline Base" folder.</div>
<div>
<br /></div>
<div>
See this Question, <a href="http://stackoverflow.com/q/16702011/642706">Tomcat deploying the same application twice in netbeans</a>, on StackOverflow.com for discussion. See <a href="http://stackoverflow.com/a/28356871/642706">my Answer</a> for my version of others’ code that finds and deletes that .xml each time you stop running your Vaadin app from NetBeans.</div>
<div>
<br /></div>
Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com2tag:blogger.com,1999:blog-4636670547456388975.post-22249937294164696272015-01-05T15:12:00.001-08:002015-02-12T15:48:32.366-08:00Event Bus For JavaAn event bus is a software library used for objects to message each other indirectly. Some objects register with the bus to be notified when certain events of interest occur. And some post events on the bus. The bus itself notifies each of the registrants when the event is posted. So the registrant objects and the event-source objects need not know about each other directly. Each may join or depart the bus at any time. You can think of it as a "pub-sub" <a href="http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">publish-subscribe</a> system, but internal to a single app.<br />
<br />
The word ‘bus’ plays off the idea of a <a href="https://en.wikipedia.org/wiki/Bus_%28computing%29">computer bus</a> where hardware components in a computer system communicate with one another.<br />
<br />
An event bus is an alternative to the <a href="http://en.wikipedia.org/wiki/Observer_pattern">Observer pattern</a>, as seen in <a href="http://en.wikipedia.org/wiki/Swing_%28Java%29">Swing</a> and other Java libraries where called <a href="http://docs.oracle.com/javase/tutorial/uiswing/events/index.html">event listeners. </a><br />
<br />
<h3>
<span style="font-family: Verdana,sans-serif;"><b>Guava EventBus</b></span></h3>
<br />
The most commonly known event bus for Java is probably the <a href="https://code.google.com/p/guava-libraries/wiki/EventBusExplained">EventBus</a> library included as part of <a href="https://github.com/google/guava">Google Guava</a>. Guava is filled with many handy pieces of goodness.<br />
<br />
Unfortunately, the Guava EventBus library inexplicably holds strong references to the registered objects. That means the calling programmer must take care to deregister each object when reaching its end-of-life. Otherwise, a memory leak occurs as the Guava EventBus will hold the object’s reference indefinitely even after the programmer intended the object to be garbage-collected. If weak references were held by the bus, then terminating objects could proceed to garbage collection while the bus detected and deregistered any such disappeared (garbage-collected) objects.<br />
<br />
Also, a minor issue, Guava EventBus supports <a href="http://en.wikipedia.org/wiki/Asynchronous_method_dispatch">asynchronous dispatch</a> through a subclass rather than by default.<br />
<br />
On the upside, we can expect Google’s team to thoroughly test and debug their work.<br />
<br />
Read <a href="http://codingjunkie.net/guava-eventbus/">this article</a> showing usage of Guava EventBus. <br />
<br />
<h3>
<span style="font-family: Verdana,sans-serif;"><b>MBassador & Mycila</b></span></h3>
<br />
A couple years ago a pair of open-source event bus projects energetically burst upon the Java scene:<br />
<ul>
<li><a href="https://github.com/bennidi/mbassador">MBassador</a> ( by <a href="https://github.com/bennidi">Benjamin Diedrichsen </a>)</li>
<li><a href="http://code.mycila.com/">Mycila PubSub</a> ( by <a href="http://about.me/mathieucarbou">Mathieu Carbou</a> ) </li>
</ul>
Both of these projects support weak references and async dispatch.<br />
<br />
<h3>
<span style="font-family: Verdana,sans-serif;"><b>SimpleBus & EventBus</b></span></h3>
<br />
The inventor of MBassador wrote a comparison of a few older Java-based event bus projects (no mention of Mycila). His more modern library is reportedly much faster and uses less memory than its predecessors including Guava EventBus.<br />
<br />
The other predecessors include:<br />
<ul>
<li><a href="https://code.google.com/p/simpleeventbus/">SimpleBus</a></li>
<li>EventBus by Michael Bushe (apparently defunct)</li>
</ul>
<h3>
GreenRobot EventBus</h3>
<div>
<br /></div>
<div>
Recently I ran across <a href="https://github.com/greenrobot/EventBus">GreenRobot EventBus</a> project, a publish/subscribe event bus optimized for Android. I have not yet tried it.<br />
<br />
Caveat: As of 2015-02, this library does <i>not</i> use weak references. This open <a href="https://github.com/greenrobot/EventBus/issues/57">issue # 57</a> requests such a feature. The main developer seems to be in favor. But not yet implemented.</div>
Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-20278685526234564992014-12-10T21:54:00.003-08:002014-12-10T21:58:49.493-08:00Handy Little Items For Postgres<h2>
<span style="color: yellow;">
Time Zone Display</span></h2>
<div>
Postgres always stores a timestamp with no time zone. The data types TIMESTAMP WITHOUT TIME ZONE and TIMESTAMP WITH TIME ZONE are both misnomers. A better name would be WITH REGARD TO TIME ZONE. </div>
<div>
<br /></div>
<div>
The "without time zone" command ignores any time zone or offset information included with data input. The date-time value is stored without any adjustment and without any recording of the specified time zone or offset. This is rarely useful, as <a href="http://justatheory.com/computers/databases/postgresql/use-timestamptz.html">explained by Postgres expert David E Wheeler</a>. </div>
<div>
<br /></div>
<div>
The "with time zone" means that any time zone or offset information included with data input is used to adjust the stored date-time to <a href="https://en.wikipedia.org/wiki/Coordinated_Universal_Time">UTC</a>. Any such time zone or offset info is discarded after the adjustment, not stored as the name suggests.</div>
<div>
<br /></div>
<div>
When displaying timestamps, Postgres applies the client's default time zone when generating a string value. What if you want to display the date-time values in UTC? </div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> SET TIME ZONE 'UTC';</span></div>
<div>
<br /></div>
<div>
What if you want to display in a specific time zone? Use a <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">proper time zone name</a>, usually a <i>continent/city</i> (or region). Avoid the 3 or 4 letter codes such as <i>EST</i> or <i>IST</i> as they are neither standardized nor unique.</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> SET TIME ZONE 'America/Montreal';</span></div>
<div>
<br />
This command affects the current session only. For example, type into a "Query" window in <a href="http://www.pgadmin.org/">pgAdmin</a>.</div>
<h2>
<span style="color: yellow;">
BYTEA Display</span></h2>
The <a href="http://www.postgresql.org/docs/current/static/datatype-binary.html">BYTEA data type</a> in Postgres is akin to a <a href="https://en.wikipedia.org/wiki/Binary_large_object">BLOB</a> in other databases. I'm guessing the name is short for "byte array". This data type is a sort of anti-data-type. When specifying BYTEA, you are telling Postgres to not bother parsing or interpreting the data. You are saying "take these bytes as-is and save them to storage without looking at them".<br />
<br />
Since Postgres has no idea what those bytes mean, it has no idea how to display them. In the old days, Postgres displayed them in a <a href="https://en.wikipedia.org/wiki/Escape_sequence">sequence of escapes</a>. Nowadays you have the choice of displaying as <a href="https://en.wikipedia.org/wiki/Hexadecimal">hexadecimal</a>. But how to specify which?<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> SET bytea_output = "hex";</span><br />
<span style="font-family: Courier New, Courier, monospace;"> SET bytea_output = "escape";</span><br />
<br />
This command affects the current session only.<br />
<div>
<br /></div>
Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com2tag:blogger.com,1999:blog-4636670547456388975.post-53501376481552974222014-11-29T12:54:00.004-08:002014-11-29T12:56:36.732-08:00What Is Whitespace?In some Java work I needed to scrub some <a href="http://www.fileformat.info/info/unicode/char/a0/index.htm">NO-BREAK SPACE</a> characters from some import data. In looking for a command in Java to trim the leading and trailing whitespace, I fell down a <a href="https://en.wikipedia.org/wiki/Alice%27s_Adventures_in_Wonderland">Rabbit Hole</a>.<br />
<div>
<br /></div>
<div>
Turns out that the Java String class offers a <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/String.html">trim</a> command. But that command has a strange definition of whitespace. Read <a href="http://closingbraces.net/2008/11/11/javastringtrim/">this blog post</a> by <a href="https://plus.google.com/102132986189328365544">Mike Kaufman</a> for details. The upshot: 'trim' only deletes characters numbered 32 (<a href="http://www.fileformat.info/info/unicode/char/20/index.htm">U+0020, SPACE</a>) and lower.</div>
<div>
<br /></div>
<div>
Then I find an interesting spreadsheet, <a href="https://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">whitespace? what's that?</a>, listing the various definitions of whitespace in Java and Unicode. There is a lot going on in the nothingness of whitespace!</div>
<div>
<br /></div>
<div>
<b>CharMatcher – Google Guava</b></div>
<div>
<br /></div>
<div>
Eventually I found a modern, flexible, easy-to-use solution:<a href="http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/CharMatcher.html"> `CharMatcher`</a> in Google Guava. See their <a href="https://code.google.com/p/guava-libraries/wiki/StringsExplained#CharMatcher">brief guide</a>. By making clever use of Predicate syntax, they make it easy to mix and match various groups of whitespace, invisible, and control characters. You can trim from the front and/or back of a string, replace, and more.<br />
<br />
Example usage:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">someText = CharMatcher.WHITESPACE.trimFrom( someText );</span></div>
Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com3tag:blogger.com,1999:blog-4636670547456388975.post-91102414769229233722014-11-09T15:39:00.004-08:002014-11-09T17:54:48.158-08:00Just use 'TEXT' type in PostgresSometimes it is the little things that trip you up, especially when learning a new tool. Like which data type to choose when creating a new database in a SQL system. But not so simple.<br />
<br />
Here are two posts that make a strong case for just using TEXT in Postgres while avoiding VARCHAR and CHAR. I agree. Wish I'd seen this long ago.<br />
<br />
<div>
<ul>
<li><a href="http://blog.jonanin.com/2013/11/20/postgresql-char-varchar/">PostgreSQL: Don't Use CHAR or VARCHAR</a> by Jon Morton, with important comments by Josh Berkus.</li>
<li><a href="http://people.planetpostgresql.org/dfetter/index.php?/archives/24-VARCHARn-Considered-Harmful.html">VARCHAR(n) Considered Harmful</a> by David Fetter.</li>
</ul>
<div>
And for more info, experimentation, and discussion, see the post <a href="http://www.depesz.com/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text/">CHAR(X) VS. VARCHAR(X) VS. VARCHAR VS. TEXT</a> by depesz.</div>
</div>
<br />
The upshot is:<br />
<div>
<ul>
<li>Use the TEXT type for all your textual needs.</li>
<li>If constraining the maximum, minimum, and content is important then define a CONSTRAINT. (No need to depend on the max length feature of varchar.)</li>
</ul>
</div>
As counter argument, see <a href="http://www.postgresonline.com/journal/archives/154-In-Defense-of-varcharx.html">IN DEFENSE OF VARCHAR(X)</a> by Leo Hsu and Regina Obe.Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com1tag:blogger.com,1999:blog-4636670547456388975.post-3934855874988684892014-11-01T17:20:00.000-07:002014-11-01T17:20:14.202-07:00Chores In TestFlightAppThe TestFlightApp.com people provide an amazing service with relatively good documentation. Unfortunately they fail to provide the most simple doc for the regular chores. I only perform these chores only on occasion, and always forget the required steps.<br />
<br />
So here’s a blog post to help remind myself. This information is for the old site before Apple acquired this company. Apple has begun pushing this service explicitly through Apple, but I continue to use the old web site; not sure if the new Apple way is different.<br />
<br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><b>Add A New User</b></span><br />
<br />
Someone wants to join my team of testers. They have no account on TestFlightApp.com.<br />
<div>
<ol>
<li>I login to TestFlightApp.com.</li>
<li>I click the "Dashboard" tab in their web site.</li>
<li>I click the third and last big green button, "Invite People".</li>
<li>I enter their email address, and send an invitation.</li>
<li>Wait for tester to do their part. Email goes out within minutes. If unreceived, remind tester to check their junk filters & folders.</li>
</ol>
<div>
The prospective tester takes their turn.</div>
</div>
<div>
<ol>
<li>Tester picks up the iOS device on which they want to test.</li>
<li>On that iOS device tester receives email from TestFlightApp.com, with subject line: "Basil Bourque has invited you to join…".</li>
<li>Tester clicks big green "Accept" button.<br />I'm not sure exactly what happens next. I think the button opens a web page to the TestFlightApp.com site which then tries to open a URL for their iOS app called "TestFlight". The user does not have such an app, so the App Store appears with an offer to purchase this app at no cost. </li>
<li>User proceeds with purchase of "TestFlight" app.</li>
<li>App opens and prompts user to create a personal account on TestFlight, with the user providing their email and inventing a password.</li>
<li>During this process, TestFlight logs this particular device's unique identifier with the TestFlightApp.com web site.</li>
</ol>
<div>
After the user has their device’ identifier logged, TestFlightApp.com sends me an email with Subject line: "So-And-So accepted your invitation". The message includes the device’s identifier. </div>
<div>
<br /></div>
<div>
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><b>Register Device Identifiers</b></span></div>
<div>
<br /></div>
<div>
A later goal is building a fresh "Provisioning Profile". To that we must register with Apple a lilt of device identifiers to be authorized to run our app. Our new user's device identifier must be added to our list registered with Apple.</div>
<div>
<br /></div>
<div>
The email mentioned above contains that identifier.</div>
<div>
<br /></div>
<div>
If you lose that email providing the identifier, or you want to look up some other testers’ device identifiers, use the TestFlightApp.com website. Click the main tab for "People". Select the checkboxes of those testers with device(s) that Apple has not yet been made aware. Over in the upper-right of the TestFlightApp.com web page find the grey "Actions" pop-up menu. Choose the menu item "Export iOS devices". Your web browser then downloads a plain text file of the identifiers of the devices owned by those checkmarked testers.</div>
<div>
<br /></div>
<div>
At this point, I need to let Apple know this device(s) is going to be added to my list of authorized testing devices. Remember that Apple limits that list to 100, revised per annum.</div>
</div>
<div>
<ol>
<li>I log into http://developer.apple.com.</li>
<li>Click the "Member Center" area of Apple's Developer site.</li>
<li>In the "Developer Program Resources" group box, click the link labeled "Certificates, Identifiers & Profiles – Manage your certificates, App IDs, devices, and provisioning profiles". <br />The next page appears with a group box "Certificates, Identifiers & Profiles".</li>
<li>Click "Devices" link. In the side-bar, you should have "Devices" > "All" selected.</li>
<li>I use the web browser's text search feature ("Edit" > "Find" in Safari) to see if the desired device identifier is in the list or not.</li>
<li>Click the "+" button in upper-right to add the identifier. Copy-paste values from the email (or the plain text file as mentioned above). TIP: Include a description of the particular device as part of the tester's name to differentiate when they own multiple devices, such as "Jane Doe – iPad Air".</li>
</ol>
<div>
As a shortcut to manually entering each of several user name + device identifiers, you can import a plain text file such as the one you downloaded early in this page. The catch is that the entire file is rejected if it contains even a single device identifier already registered. I often find it easier to do one at a time.</div>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><b>Provisioning Profile</b></span><br />
<br />
Now it is time to build that fresh "Provisioning Profile". This encrypted security document lists our registered devices identifiers Apple is granting permission to run my app without that app being delivered through the App Store. This Provisioning Profile will eventually be integrated into a future build of my app intended for distribution to testers.<br />
<div>
<br /></div>
<div>
To create a fresh Provisioning Profile, use that same "Certificates, Identifiers & Profiles" group box page at the Apple Developer site. </div>
<div>
<br /></div>
<div>
<ol>
<li>In the side bar, choose "iOS Apps" > "Provisioning Profiles" > "Distribution". </li>
<li>Select the "Distribution" > "Ad Hoc" radio button.</li>
<li>Follow the Wizard-like steps.</li>
<li>On the step for "Select devices.", click the checkbox labeled "Select All" and continue.</li>
<li>On the step for "Name this profile and generate.", enter a name similar to "Ad Hoc test distrib 2014-11-01".</li>
<li>On that same step, click the "Generate" button.</li>
<li>On a following step, click the "Download" button to download the newly generated Provisioning Profile to your local Mac. <br />That file will be named something like "Ad_Hoc_test_distrib_20141101.mobileprovision".</li>
<li>Locate that local file on your Mac.</li>
<li>Open your app’s project in Xcode.</li>
<li>Double-click on the .mobileprovision file causing it to be opened by Xcode.</li>
</ol>
<div>
Now I rebuild the project to incorporate that fresh Provisioning Profile. I am using Xcode 5 (not 6).</div>
</div>
<div>
<ol>
<li>Hold down the OPTION key while choosing the menu item "Product" > "Clean Build Folder" and confirm.</li>
<li>Set the "Active Scheme" pop-up in far upper-left corner to "iOS Device".</li>
<li>Choose menu item "Product" > "Archive".<br />The Organizer window appears.</li>
<li>In the Organizer, click "Distribute" button.</li>
<li>In Wizard-like window, choose radio button for "Save for Enterprise or Ad Hoc Distribution" (Ad Hoc is what I'm doing).</li>
<li>IMPORTANT – In next step of the Wizard, "Choose a profile to sign with", <u>change the "Provisioning Profile" pop-up menu to your fresh one</u> rather the default old one you used previously. This pop-up is why we named the .mobileprovision file with a date and the words "Ad Hoc", to make selection easier here.</li>
<li>Click "Export" button.<br />Wait a couple minutes for a Save As dialog to appear suggesting a ".ipa" file name extension.</li>
<li>In that Export save dialog, I create a new folder named with the date and purpose. Save into that staging folder.</li>
</ol>
<div>
Done with the build process. Now it is time to upload to TestFlight for distribution to our users.</div>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><b>Upload To TestFlight</b></span><br />
<div>
<ol>
<li>Login to TestFlightApp.com.</li>
<li>Click the main tab for "Dashboard".</li>
<li>Click the first large green button, "Upload a Build".</li>
<li>In the page that appears, write your Release Notes, indicating a focus for your testers’ work.</li>
<li>Drag-and-drop the .ipa file from your staging folder to the dashed-line box on the same web page, and click green "Upload" button.</li>
<li>Wait patiently for your app to upload.</li>
</ol>
</div>
<br />
<br />
<br />Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com5tag:blogger.com,1999:blog-4636670547456388975.post-21533734634245475012014-10-15T15:14:00.003-07:002014-10-15T15:17:59.952-07:00UUID Converter For VaadinHere is a class to convert a <a href="http://docs.oracle.com/javase/8/docs/api/java/util/UUID.html">java.util.UUID</a> object to String for use in Vaadin. Originally written by a team member at Vaadin, I modified their source code to output lowercase <a href="http://en.wikipedia.org/wiki/Hexadecimal">hexadecimal</a> characters as required by the <a href="http://en.wikipedia.org/wiki/Universally_unique_identifier">UUID</a> spec.<br />
<br />
I filed a <a href="http://dev.vaadin.com/ticket/14493">feature request ticket</a> with Vaadin to bundle such a class with Vaadin.<br />
<br />
Source code…<br />
<br />
<code>
import com.vaadin.data.util.converter.Converter;<br />
import java.util.Locale;<br />
import java.util.UUID;<br />
<br />
/**<br />
* Modified by Basil Bourque to ensure output of hex string is in lowercase as required by the UUID spec. 2014-08.<br />
*<br />
* @author petter@vaadin.com<br />
*/<br />
public class UUIDToStringConverter implements Converter<String , UUID><br />
{<br />
private static final String NULL_STRING = "(none)";<br />
<br />
@Override<br />
public UUID convertToModel ( String value , Class<? extends UUID> targetType , Locale locale ) throws ConversionException<br />
{<br />
try {<br />
return value == null || value.isEmpty() || value.equals( NULL_STRING ) ? null : UUID.fromString( value );<br />
} catch ( IllegalArgumentException ex ) {<br />
throw new ConversionException( ex );<br />
}<br />
}<br />
<br />
@Override<br />
public String convertToPresentation ( UUID value , Class<? extends String> targetType , Locale locale ) throws ConversionException<br />
{<br />
return value == null ? NULL_STRING : value.toString().toLowerCase(); // The UUID spec *requires* hex-string output to be lowercase. Must tolerate uppercase for input.<br />
}<br />
<br />
@Override<br />
public Class<UUID> getModelType ()<br />
{<br />
return UUID.class;<br />
}<br />
<br />
@Override<br />
public Class<String> getPresentationType ()<br />
{<br />
return String.class;<br />
}<br />
}<br />
</code>
<br />
xxBasil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com1tag:blogger.com,1999:blog-4636670547456388975.post-7511608200383557512014-10-13T00:16:00.000-07:002014-10-13T00:42:03.270-07:00Installing Postgres 9.4Here's a reminder checklist of the steps I take when installing successive beta versions (1, 2, and 3, so far) of Postgres 9.4 on my Macs.<br />
<br />
<b>Installer</b><br />
<br />
The Postgres support company <a href="http://http%3B//www.EnterpriseDB.com/">EnterpriseDB</a> graciously supplies installers for Mac OS X as a courtesy to the community. You may reach their site via the <a href="http://www.postgresql.org/download/">Download page</a> of the usual <a href="http://www.postgresql.org/">Postgres site</a>. For beta versions look for the paragraph labeled "Beta/RC Releases and development snapshots (unstable)", and find the link to click. On the next page, look for the link near the text "offsite link". Currently takes you to the <a href="http://www.enterprisedb.com/products-services-training/pgdevdownload">Early Experience page</a> of EnterpriseDB. Click a link to download a <a href="http://en.wikipedia.org/wiki/Apple_Disk_Image">DMG file</a> named something like "postgresql-9.4.0-beta3-osx.dmg".<br />
<br />
<b>Users</b><br />
<br />
The Postgres superuser "postgres" is already created by the installer.<br />
<br />
Next we need to create a not-quite-so-super user. This is done in "Login Roles" in pgAdmin, not the "Group Roles" list. Choose a name and password for this user, and write it down. The create this user in pgAdmin using a dialog or run the following SQL. After creation, refresh pgAdmin, and context-click the user to choose "Properties" where you can define a password on the "Definition" tab.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">CREATE ROLE your_admin_user_name_goes_here LOGIN</span><br />
<span style="font-family: Courier New, Courier, monospace;"> NOSUPERUSER INHERIT CREATEDB CREATEROLE REPLICATION;</span><br />
<div>
<br /></div>
Next, create a group role to be used by your application. Let's imagine your app is named "Example" in general and "example_" in Postgres. We move attention from "Login Roles" to the "Group Roles" list in pgAdmin. Again, do this in the pgAdmin wizard-like dialog or use this SQL.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">CREATE ROLE example_app_role_</span><br />
<span style="font-family: Courier New, Courier, monospace;"> NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION;</span><br />
<br />
As done above for the admin user, context-click the user to choose "Properties" where you can define a password on the "Definition" tab. And, of course, you are writing down these passwords.<br />
<br />
Now create a user to be assigned to that role. Again, use either dialog or this SQL:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">CREATE ROLE example_app_ LOGIN</span><br />
<span style="font-family: Courier New, Courier, monospace;"> NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION;</span><br />
<span style="font-family: Courier New, Courier, monospace;">GRANT example_app_role_ TO example_app_;</span><br />
<span style="font-family: Courier New, Courier, monospace;">COMMENT ON ROLE example_app_ IS 'For connections from our Example app.';</span><br />
<br />
<br />
<b>Restore</b><br />
<br />
As I am installing a succession of beta versions, I already have a backup of my desired database. I used pgAdmin's "Backup" feature to create a .backup file. That chore is described in my previous blog entry.<br />
<br />
That backup contains just about every aspect of my database, except one: Users & Passwords. That is why we defined our admin user, app role, and app user in those steps above. Those users and roles must be in place for the restore feature to work. The restore references ownership of various objects by those users/roles.<br />
<br />
So now I want to restore that database to my new Postgres. No go. The restore process cannot create the database. You must create the database manually, such as in pgAdmin. Use the same name, but need take no further steps.<br />
<br />
Context-click on the new database to choose the Restore feature. In the dialog, choose the character encoding to match the original. Not sure of this is required, but probably. Use the button to choose the .backup file to be imported. Finally click the main button to execute the restore. The restoration may take a while. Eventually look to the "Messages" tab of the window to show the progress and completion. Look at the bottom of that report to see if any errors or issues arose.<br />
<br />
<b>Permissions</b><br />
<br />
Now we have users defined and we have a database restored. Now we have combine them. The app role we defined must be given permission to work with that database. Execute SQL such as the following, after you have done your homework to study such permissions.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO example_app_role_;</span><br />
<span style="font-family: Courier New, Courier, monospace;">GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO example_app_role_;</span><br />
<br />
<b>Done</b><br />
<br />
That's it. Your database should be back in order. Tables and data should be there. Type "<span style="font-family: Courier New, Courier, monospace;">table my_table_name_;</span>" in the SQL window to see all rows, as a quick test. Any functions, domains, etc. you defined should be intact.<br />
<br />
<b>Alternative: pg_restore</b><br />
<br />
Instead of this backup-destroy-restore process, you can go another route. Postgres has a nifty <a href="http://www.postgresql.org/docs/9.4/static/app-pgrestore.html">pg_restore</a> feature for doing major upgrades in place. I've no experience with this yet.<br />
<div>
<br /></div>
<br />Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-24702862401054005942014-10-12T22:14:00.002-07:002014-10-12T22:14:57.803-07:00Uninstalling Postgres 9.4My reminder checklist for uninstalling Postgres 9.4 beta versions. These instructions assume the use of the Postgres installers provided to the community as a courtesy by <a href="http://www.enterprisedb.com/">EnterpriseDB</a>. For more info, read <a href="http://stackoverflow.com/a/9240197/642706">this answer</a> in StackOverflow.com.<br />
<br />
<b>Backup</b><br />
<br />
First backup. Use pgAdmin app to select the desired database(s). On each database context-click to choose the Backup command. Go with default options, including "Custom" format which is a strange name for the native binary format. Choosing "Plain Text" creates SQL statements which is interesting but verbose and slow. The only setting you set is to click the button to choose a folder and specify a desired name for the backup file. Include the ".backup" extension yourself. While most Mac apps are built to add an extension, pgAdmin does not.<br />
<br />
<b>Run Uninstaller App</b><br />
<br />
In the root folder (not your user home folder), look in Library folder to find the PosgreSQL folder. So that would be: /Library/PostgreSQL/ path. In there find one or more versions of Postgres. Within a version find the app named <span style="font-family: Courier New, Courier, monospace;">uninstall-postgresql</span>. Run that app, supply your system password.<br />
<br />
<b>Delete Config File</b><br />
<br />
Delete this file:<span style="font-family: Courier New, Courier, monospace;">/etc/postgres-reg.ini</span>.<br />
<br />
<b>Delete User</b><br />
<br />
The installer created a Unix user to your Mac named 'postgres'. If eradicating Postgres, you may want to delete that user account. For re-installing a new Beta versions of Postgres, I don't bother. The installer seems to tolerate that extant account.<br />
<br />
<b>Delete Apps</b><br />
<br />
Check your usual Applications folder. If the PostgreSQL folder remains there, delete it.<br />
<br />
<b>Delete pgAdmin Preferences</b><br />
<br />
If you used the pgAdmin app for administering your databases, its preferences file remains. No big deal. I don't know where it lives. Perhaps the Google would tell you.<br />
<br />
<b>No Longer Used</b><br />
<br />
In the old days you would delete the file /etc/sysctl.conf. I do not find that file with Postgres 9.4. I suspect the reason is that 9.4 changed dramatically. Previously a Unix setting was needed on your Mac to enlarge shared buffers. Memory for the database cache is now done differently, so that setting is no longer needed. And therefore that configuration file is no longer needed. I have not confirmed this theory, just a guess on my part.<br />
<br />Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com4tag:blogger.com,1999:blog-4636670547456388975.post-12911483293315596852014-10-02T14:51:00.004-07:002014-10-02T15:06:04.028-07:00Track Date-Time Of Row Creation & Modification In PostgresHere is some example code for using Postgres to automatically track when a row is added to a table and when a row is modified.<br />
<br />
Solution requires three steps.<br />
<br />
<span style="font-family: Trebuchet MS, sans-serif;"><b>STEP 1 — Columns</b></span><br />
<br />
First, create a column of type `TIMESTAMP WITH TIME ZONE`. Do not abbreviate to `TIMESTAMP` as that is defined by the SQL spec as `TIMESTAMP WITHOUT TIME ZONE` which is almost certainly not what you want, as <a href="http://justatheory.com/computers/databases/postgresql/use-timestamptz.html">explained here</a> by Postgres expert David E. Wheeler.<br />
<br />
Name the column exactly the same on each table you want updated. To track creation and mod date-times, I use the names:<br />
<div>
<ul>
<li>row_created_</li>
<li>row_modified_</li>
</ul>
<div>
In my own names, I avoid abbreviations. Also, I always include a trailing underscore to avoid collision with reserved keywords, as suggested by the SQL spec. </div>
<div>
<br /></div>
<div>
Those columns are marked `NOT NULL`. Each has a `DEFAULT` of the current moment, set by calling `CLOCK_TIMESTAMP()`. Note that Postgres has three kinds of "now": (1) The actual current moment read from the computer’s clock, (2) When the statement started execution, (3) When the transaction started execution. One could arguably choose any of those three for their own creation and mod values.</div>
<div>
<br /></div>
<div>
You may or may not want a default value for your `row_modified_` column. Some people argue for the precision of the semantics that a new record has not yet been modified. My counter-argument is two-fold: (a) That means allowing NULL values, and I am of the camp believing NULL to be the work of the devil, (b) In my experience, I rarely look at creation date-time, but just scan the mod column where I then find missing values (nulls) to be distracting/confusing.</div>
<div>
<br /></div>
<div>
<b><span style="font-family: Trebuchet MS, sans-serif;">STEP 2 — Function</span></b></div>
<div>
<br /></div>
<div>
Secondly, define a function to generically update any table as long as that table has a column named exactly as we expect.</div>
</div>
<br />
A "function" is an old-fashioned name for a chunk of server-side code to be executed at run-time. We define this method as a database object, designating a name and so on just like a table or column.<br />
<br />
To write a function, we need a programming language more powerful/flexible than SQL. Postgres is capable of running any number of programming languages on the server side, including Java, Perl, Python, and so on. But one language was created expressly for use within Postgres: <a href="http://en.wikipedia.org/wiki/PL/pgSQL">PL/pgSQL</a>. This language is nearly always included with any Postgres installation ("cluster" in Postgres lingo) whereas the other languages may not be installed by default. Note how our code below declares the language of the function.<br />
<br />
The keyword `NEW` provides the generic ability we need to address any table. When the trigger causes the function to run, the word `NEW` represents the table being updated.<br />
<br />
Our function calls another function, one of <a href="http://www.postgresql.org/docs/current/static/functions-datetime.html">many date-time functions</a> built into Postgres. As mentioned above, these functions vary.<br />
<br />
<span style="font-family: Trebuchet MS, sans-serif;"><b>STEP 3 — Trigger</b></span><br />
<br />
To run that function, we must define a trigger. A trigger is a rule living on the Postgres server that says a function should be run upon certain events happening. In our case, the event we care about is when a record is being modified (`UPDATE` in SQL terminology). <br />
<br />
Postgres allows a trigger to run <i>before</i> the row in the actual database is affected by an event operation, or <i>after</i> the event operation. In our case we want to run the trigger <b>before</b> the record is actually updated. Running our trigger after an update would cause an endless loop as our act of setting the current date-time on the `row_modified_` column would be another update which would necessitate our trigger running again, and again, and again forever.<br />
<br />
<span style="font-family: Trebuchet MS, sans-serif;"><b>Example Code</b></span><br />
<br />
Here is some example code showing the above three steps.<br />
<br />
All three steps can be rolled into a single SQL operation inside a transaction. Note the `BEGIN` and `COMMIT` for the transaction boundaries.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">BEGIN;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">ALTER TABLE customer_</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ADD COLUMN row_modified_ TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT clock_timestamp();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">ALTER TABLE invoice_</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ADD COLUMN row_modified_ TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT clock_timestamp();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">ALTER TABLE customer_</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ADD COLUMN row_created_ TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT clock_timestamp();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">ALTER TABLE invoice_</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ADD COLUMN row_created_ TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT clock_timestamp();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">CREATE OR REPLACE FUNCTION update_row_modified_function_()</span><br />
<span style="font-family: Courier New, Courier, monospace;">RETURNS TRIGGER </span><br />
<span style="font-family: Courier New, Courier, monospace;">AS </span><br />
<span style="font-family: Courier New, Courier, monospace;">$$</span><br />
<span style="font-family: Courier New, Courier, monospace;">BEGIN</span><br />
<span style="font-family: Courier New, Courier, monospace;"> -- ASSUMES the table has a column named exactly "row_modified_".</span><br />
<span style="font-family: Courier New, Courier, monospace;"> -- Fetch date-time of actual current moment from clock, rather than start of statement or start of transaction.</span><br />
<span style="font-family: Courier New, Courier, monospace;"> NEW.row_modified_ = clock_timestamp(); </span><br />
<span style="font-family: Courier New, Courier, monospace;"> RETURN NEW;</span><br />
<span style="font-family: Courier New, Courier, monospace;">END;</span><br />
<span style="font-family: Courier New, Courier, monospace;">$$ </span><br />
<span style="font-family: Courier New, Courier, monospace;">language 'plpgsql';</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">CREATE TRIGGER row_mod_on_customer_trigger_</span><br />
<span style="font-family: Courier New, Courier, monospace;">BEFORE UPDATE</span><br />
<span style="font-family: Courier New, Courier, monospace;">ON customer_ </span><br />
<span style="font-family: Courier New, Courier, monospace;">FOR EACH ROW </span><br />
<span style="font-family: Courier New, Courier, monospace;">EXECUTE PROCEDURE update_row_modified_function_();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">CREATE TRIGGER row_mod_on_invoice_trigger_</span><br />
<span style="font-family: Courier New, Courier, monospace;">BEFORE UPDATE</span><br />
<span style="font-family: Courier New, Courier, monospace;">ON invoice_ </span><br />
<span style="font-family: Courier New, Courier, monospace;">FOR EACH ROW </span><br />
<span style="font-family: Courier New, Courier, monospace;">EXECUTE PROCEDURE update_row_modified_function_();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">COMMIT;</span><br />
<br />
<br />Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com4tag:blogger.com,1999:blog-4636670547456388975.post-70370491224776329822014-09-20T00:12:00.001-07:002014-09-20T00:12:41.733-07:00Homework For Tim CookAfter many frustrating hours wasted on many interactions with Apple for submitting an iOS app to the App Store, I have this wish:<br />
<br />
Lock <a href="http://en.wikipedia.org/wiki/Tim_Cook">Tim Cook</a> in a room alone with nothing but:<br />
<br />
<br />
<ul>
<li>A cup of coffee.</li>
<li>A MacBook running:</li>
<ul>
<li>Xcode with a completely built iOS app.</li>
<li>Safari with a pair of windows for:</li>
<ul>
<li>The <i>iTunesConnect</i> site.</li>
<li>The <i>developer.apple.com</i> site. </li>
</ul>
</ul>
<li>A relief bucket.</li>
</ul>
<br />
<br />
Do not let him leave the room until the app has been successfully submitted to the App Store.Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-67805348424547804082014-08-06T16:41:00.003-07:002014-08-06T16:44:02.059-07:00Postgres User For AppInstalling Postgres means creating a new operating-system (Unix) user, by default named "postgres".<br />
<br />
At the same time a superuser is created <i>within</i> the Postgres environment by the same name. This superuser can do anything, including dropping a table and even deleting an entire database (catalog).<br />
<br />
Postgres experts commonly suggest that you create a new user with most but not all of the powers of the superuser. Creation and deletion of databases should be omitted. This is the basic administrator user that you use typically use in day-to-day work. This admin user is what you usually use as the login user in pgAdmin or your other admin tools.<br />
<br />
When developing an app, the data-access layer will need to connect to the Postgres database as a user. Again, experts commonly suggest you create a Postgres user for this purpose. The app-user normally should not have the power to create or delete tables, as well as schema and databases. Even some individual tables may be read-only for this user, without powers to insert, update, or delete.<br />
<br />
You may even want to create multiple app-users, each with different powers depending on what parts of the app will be engaged by the human user. For example, bookkeepers may have read-write access to tables that salespeople do not. You can enforce this access at the database engine (Postgres) as well as at your app (ex: Java & <a href="https://www.vaadin.com/">Vaadin</a>).<br />
<br />
Your app may be calling functions, such as the <a href="http://www.postgresql.org/docs/9.4/static/uuid-ossp.html">UUID-OSSP library</a>. Those functions are protected, and you must grant permission to those as well.<br />
For a basic app, the app-user might have <a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> access to all the tables and the functions. Here is the SQL code you must run after adding a table or function to grant powers to your app user. The code assumes you used the default schema named <span style="font-family: "Courier New",Courier,monospace;">public</span>, so modify as needed.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO acme_app_;<br />GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO acme_app_;</span>Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-34704435086111024252014-07-15T19:21:00.006-07:002014-07-15T19:23:43.518-07:00NetBeans Debugger – Show Value as 'toString'NetBeans 8 (and earlier) has an important debugging feature hidden away: Show a variable’s value as rendered by its own <span style="font-family: "Courier New",Courier,monospace;">toString</span> method.<br />
<br />
You can expose an additional column for this value in the debugger’s <i>Variables</i> pane. Notice the orange splotch icon tucked away by itself in the upper-right corner. Click that icon to present a <i>Change Visible Columns</i> dialog. Check the checkbox labeled <i>String Value: String representation of the value</i>.<br />
<br />
Of course this feature requires safe-and-sane implementations of <span style="font-family: "Courier New",Courier,monospace;">toString</span> method on exposed objects. The risk of misbehaved implementations is presumably the reason this column is not exposed by default.<br />
<br />
<div style="text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjORAO300a6-5A7hO2rTh3oIWQXMLRJKvP_TyzncHciyTRPSuNn4Ma1Y5OiWzbUspg2k9gYeirqr9-JXxaaB_6gyYv_FdODkO8Rlw0bQM9CEAH_93sJCbWGPlUmAAajb67-5MlkGmxijM/s1600/netbeans_string_value.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="Screen shot of "Change Visible Columns" dialog box" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjORAO300a6-5A7hO2rTh3oIWQXMLRJKvP_TyzncHciyTRPSuNn4Ma1Y5OiWzbUspg2k9gYeirqr9-JXxaaB_6gyYv_FdODkO8Rlw0bQM9CEAH_93sJCbWGPlUmAAajb67-5MlkGmxijM/s1600/netbeans_string_value.png" height="275" title="" width="400" /></a></div>
<br />Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com1tag:blogger.com,1999:blog-4636670547456388975.post-29378713175880830642014-07-10T17:18:00.000-07:002014-07-10T17:22:23.609-07:00Example Use of Java Try-With-Resource For JDBCHere is a nice nugget of example code for how to use a JDBC PreparedStatement with the try-with-resource feature in Java. This feature automatically closes resources even if any exceptions are thrown.<br />
<br />
Note how for a <span style="font-family: Courier New, Courier, monospace;">PreparedStatement</span> we must nest one try-with-resource inside another. Apparently an exception thrown by the inner one will be caught by the outer one.<br />
<br />
This example is taken from <a href="http://stackoverflow.com/a/8066594/642706">this answer</a> in StackOverflow. I am posting here for my copy-paste convenience.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">public List<User> getUser(int userId) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> String sql = "SELECT id, username FROM users WHERE id = ?";</span><br />
<span style="font-family: Courier New, Courier, monospace;"> List<User> users = new ArrayList<>();</span><br />
<span style="font-family: Courier New, Courier, monospace;"> try (Connection con = DriverManager.getConnection(myConnectionURL);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> PreparedStatement ps = con.prepareStatement(sql);) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ps.setInt(1, userId);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> try (ResultSet rs = ps.executeQuery();) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> while(rs.next()) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> users.add(new User(rs.getInt("id"), rs.getString("name")));</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> } catch (SQLException e) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> e.printStackTrace();</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return users;</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<br />
<br />
<b>Trailing Semicolon</b><br />
<br />
And speaking of copy-paste, I can also share a small but important fact: Note the trailing semicolon on the second line of the outer "try". Two statements within the try, each terminated by a semicolon. Early drafts of this feature forbade the trailing semicolon and many folks mistakenly believe that is still the case. But in the final release the Java team realized the convenience of copy-pasting lines without having to remember to remove (or add) the trailing semicolon statement terminator. I suggest always including that optional semicolon.<br />
<div class="post-text" style="background-color: white; border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin: 0px 5px 5px 0px; padding: 0px; vertical-align: baseline; width: 660px; word-wrap: break-word;">
<code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span></code></div>
Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-15483879011402004052014-04-13T22:34:00.001-07:002014-04-13T22:55:05.154-07:00Why No Awards For Tech Writers?Why is there no <a href="http://en.wikipedia.org/wiki/Pulitzer_Prize">Pulitzer Prize</a> or <a href="http://en.wikipedia.org/wiki/Nobel_prize">Nobel Prize</a> for technical writers?<br />
<br />
My nominations:<br />
<ul>
<li><a href="http://en.wikipedia.org/wiki/Kathy_Sierra">Kathy Sierra</a></li>
<li><a href="http://www.oreilly.com/pub/au/249">Matt Neuburg</a></li>
<li><a href="http://en.wikipedia.org/wiki/Cary_Lu">Cary Lu</a></li>
<li><a href="http://arstechnica.com/author/john-siracusa/">John Siracusa </a></li>
<li><a href="http://en.wikipedia.org/wiki/Esther_Dyson">Esther Dyson </a></li>
<li><a href="http://en.wikipedia.org/wiki/John_Battelle">John Battelle</a></li>
<li><a href="http://en.wikipedia.org/wiki/Danny_Goodman">Danny Goodman </a></li>
</ul>
Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0tag:blogger.com,1999:blog-4636670547456388975.post-80014010280077357082014-04-08T14:48:00.002-07:002014-04-08T15:00:12.050-07:00Quick Start to Logging with SLF4J and Logback for a Maven-based ProjectI followed this informative but slightly out -of-date article, <a href="https://wiki.base22.com/display/btg/How+to+setup+SLF4J+and+LOGBack+in+a+web+app+-+fast">How to setup SLF4J and LOGBack in a web app - fast</a>, to get started with logging in my <a href="https://www.vaadin.com/">Vaadin</a> web app. Here is my description of the same steps using <a href="https://www.netbeans.org/">NetBeans</a> 8 with <a href="https://en.wikipedia.org/wiki/Java_version_history#Java_SE_8_.28March_18.2C_2014.29">Java 8</a> hooked up to <a href="http://tomcat.apache.org/">Tomcat</a> 8 on a Mac mini running Mavericks.<br />
<br />
First create your Maven-based project. In my case, I'm using version 1.1.1 of the <a href="http://plugins.netbeans.org/plugin/50531/vaadin-plug-in-for-netbeans">Vaadin Plugin for NetBeans</a> to create a new Vaadin 7.1 project.<br />
<br />
Add the logging façade library, <a href="http://www.slf4j.org/">SLF4J</a>.<br />
<ol>
<li>In the NetBeans project navigator pane, context-click on the Dependencies item.</li>
<li>Choose <i>Add Dependency</i>. </li>
<li>Type: <span style="font-family: "Courier New",Courier,monospace;">slf4j-api</span></li>
<li>Open the <span style="font-family: "Courier New",Courier,monospace;">org.slf4j : slf4j-api</span> item to choose the latest version.</li>
</ol>
I find that repository listing in NetBeans is consistently inconsistent, in other words, psycho-crazy. Close that dialog, repeat the same steps, and get a different list of version numbers. Sometimes you see later versions, sometimes you see only earlier versions. So check the web site for the desired dependency (SLF4J in this case) to determine the true latest version. Repeat that dialog a few times until it randomly decides to show you a version number close to the true latest. Choose that item. Later you can edit your "pom.xml" to the true latest.<br />
<br />
In a fashion similar to SLF4J, let's add <a href="http://logback.qos.ch/">Logback</a>. Logback is a direct implementation of that SLF4J façade. You can use nearly any other Java-based logging frameworks in conjunction with an adapter. Logback needs no adapter. Logback is the successor to Log4J, both of which were created by the same man.<br />
<br />
We need two jars for LogBack, "classic" and "core". However, adding a dependency for "classic" will automatically get us "core". <br />
<ol>
<li>In the NetBeans project navigator pane, context-click on the Dependencies item.</li>
<li>Choose <i>Add Dependency</i>. </li>
<li>Type: <span style="font-family: "Courier New",Courier,monospace;">logback-classic</span></li>
<li>Open the <span style="font-family: "Courier New",Courier,monospace;">ch.qos.logback : logback-classic</span> item.</li>
<li>Choose the latest version offered.</li>
</ol>
Again, you'll probably get a not-quite-right list of versions. Take the latest offered, and update later.<br />
<br />
Save all your files, and do a clean-and-build of your project (Hammer & Broom icon) to get Maven to do its duty. You should find in the project navigator pane a new item <span style="font-family: "Courier New",Courier,monospace;">Other Sources</span>. Expand that item to find a <span style="font-family: "Courier New",Courier,monospace;">src/main/resources</span> item.<br />
<ol>
<li>Context-click the <span style="font-family: "Courier New",Courier,monospace;">src/main/resources</span> item to create a new XML file.</li>
<li>Name the new XML file: <span style="font-family: "Courier New",Courier,monospace;">logback.xml</span></li>
<li>Into that file, past the following XML text seen below.</li>
<li>Change the XML text, replacing "com.example" with your own project’s top package.</li>
</ol>
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><?xml version="1.0" encoding="UTF-8"?><br /><configuration><br /><br /> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><br /> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><br /> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern><br /> </encoder><br /> </appender><br /> <br /> <logger name="com.example" level="TRACE"/><br /><br /> <root level="debug"><br /> <appender-ref ref="STDOUT" /><br /> </root><br /> <br /></configuration></span></span> <br />
<br />
This XML is different than that older article, having replaced the deprecated <span style="font-family: "Courier New",Courier,monospace;">layout</span> with an <span style="font-family: "Courier New",Courier,monospace;">encoder</span>. This XML configures Logback to send your logging messages to the NetBeans console. You'll need to make alterations for use when deployed to production, but this should get you started in development.<br />
<br />
Now try it out. In your Vaadin app, locate the <span style="font-family: "Courier New",Courier,monospace;">MyVaadinUI.java</span> file that drives your app.<br />
<ol>
<li>Add an import: <span style="font-family: "Courier New",Courier,monospace;">import org.slf4j.*;</span></li>
<li>At the top of your class definition, add the line:<br /><span style="font-family: "Courier New",Courier,monospace;">static final Logger LOG = LoggerFactory.getLogger(MyVaadinUI.class);</span></li>
<li>In the init method of this class, add the following code to see if logging works.</li>
</ol>
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> LOG.trace("Yogi - Logging Test - Trace");<br /> LOG.debug("Yogi - Logging Test - Debug");<br /> LOG.info("Yogi - Logging Test - Info");<br /> LOG.warn("Yogi - Logging Test - Warn");<br /> LOG.error("Yogi - Logging Test - Error");</span></span><br />
<br />
Run your Vaadin app. You may need to do a clean-and-build (Hammer & Broom icon). On one of the tabs in the NetBeans "Output" console pane you should see your messages.<br />
<br />
To update the version numbers of <i>SLF4J</i> and <i>Logback</i>, look in the NetBeans project navigator pane. Expand the <i>Project Files</i> item to locate and open "pom.xml" file. Search for "slf4j" and "logback" and update each one’s <span style="font-family: "Courier New",Courier,monospace;">version</span> tag with the number you know to be current. Saving the XML file may cause Maven to do its duty. If not, try a clean-and-build.<br />
<br />
<b>Caveat:</b> I am a Maven and SLF4J and Logback triple newbie. The above steps worked for me, but I cannot say that I understand them fully. Follow these steps at your own risk. Backup your project first.Basil.Bourquehttp://www.blogger.com/profile/03457065228238134738noreply@blogger.com0