Maven Integration for Eclipse

Previously I was using an old Maven integration for Eclipse, version 0.0.11, which I got from http://m2eclipse.codehaus.org/update.  The plugin was horribly slow and seemed to sometimes interfere with my builds.

Today I upgraded to the latest, version 0.9.4, from http://m2eclipse.sonatype.org/update/ and things are moving much more smoothly.  You can learn more at Maven Integration for Eclipse.

In Windows > Preferences > Maven I only turned on Download Artifact Sources and Download Artifiact JavaDoc.  Download repository index updates on startup is on by default but I turned it off after receiving this advice from a fellow developer, Bill Crook.

It’s unclear to me how the m2 plugin uses the indexes so I don’t think I can answer you. 🙂 Enabling it causes the plugin to rescan the entire repository if i remember correctly. I personally am not willing to have Eclipse do a full file scan of the local repository each time i start for unknown reasons. if you don’t mind the incurred overhead, go ahead and enable it!

The Maven plugin has a nice dependency feature which Bill Crook explains well.

There will come a time when you need to work on two projects simultaneously. Additionally, there will probably be a dependency from one project to another. The key to doing this effectively is understanding workspace resolution. Workspace resolution is a concept of the m2eclipse plugin. The way this works is that the plugin scans all projects in your workspace and analyzes the poms. Based on group and artifact ID’s the plugin will know if there are interdependencies between your projects. Once the plugin has successfully detected the dependency between projects, you can jump from one project source into another when jumping into methods (via control-click or F3).

There is one important caveat to this, versions. In addition to looking at group and artifact ID’s, the m2eclipse plugin will look at versions to determine if the project for a dependency is in the current workspace. Because of this you must make sure the versions match. Let’s take the example of projects A and B in your workspace. Assume A has a dependency on version 2.0.0.1 of B. Now, if the version of project B in your workspace is 3.0-SNAPSHOT, workspace resolution will NOT work. Can you figure out how to make this work? If you guessed, update the pom of project A to depend on 3.0-SNAPSHOT, you are correct. The moral of the story is be aware of versions when trying to get workspace resolution working.

You will know that workspace resolution is not functioning properly if you see duplicates of the same class when doing searches with control-shift-t. This behavior makes sense when you think about it as Eclipse sees two of these classes in your workspace. For example, continuing with projects A and B as above, let’s assume there is a class Foo in project B. Eclipse would find class Foo in project B source (as java source in your workspace) as well as in version 2.0.0.1 of B (as a class file in jar dependency).

Now if someone would improve the Perforce plugin…

Jumping to different parts of a page using a dropdown

It is relatively simple to dynamically create a dropdown from which you can jump to different parts of a page using JavaScript and ATG DSPEL.

First create the dropdown.

<form name="jumpTo" action=".">
  <dspel:droplet name="/atg/dynamo/droplet/ForEach">
    <dspel:param name="array" param="categories"/>
    <dspel:setvalue param="category" paramvalue="element"/>
    <dspel:oparam name="outputStart">
      <select name="names">
    </dspel:oparam>
    <dspel:oparam name="output">
      <dspel:getvalueof id="index" param="index"/>
      <c:set var="catShortName" value="cat${index}"/>
      <option value="<c:out value="${catShortName}"/>">
        <dspel:valueof param="category.name"/>
      </option>
    </dspel:oparam>
    <dspel:oparam name="outputEnd">
      </select>
    </dspel:oparam>
  </dspel:droplet>
</form>

Next create the button outside of the form for jumping to different parts of the page. I learned about the window.location.hash from this article. And I learned about how to access the selected value from the dropdown from this article.

 <input type="image" src="/img/buttons/update.gif"
   onClick="window.location.hash=
document.jumpTo.names.options[document.jumpTo.names.selectedIndex].value">

Finally you create the name anchors throughout your document.

<dspel:droplet name="/atg/dynamo/droplet/ForEach">
  <dspel:param name="array" param="categories"/>
  <dspel:setvalue param="category" paramvalue="element"/>
  <dspel:oparam name="output">

    <%-- magazine category --%>
    <dspel:getvalueof id="index" param="index"/>
    <c:set var="catShortName" value="cat${index}"/>
    <a name="<c:out value="${catShortName}"/>"
       id="<c:out value="${catShortName}"/>">
      <dspel:valueof param="category.name"/>
    </a>

  </dspel:oparam>
</dspel:droplet>

Gmail, SPF, and Broken Email Forwarding?

I read this article on Slashdot, Gmail, SPF, and Broken Email Forwarding?, which explains how email forwarding to Gmail and possibly other service providers may sometimes silently fail.

Background: Like many people, I have me@mydomain.com as my public facing Email address. When Email comes into my server, I forward it to me@gmail.com. But since my friend has published SPF (Sender Policy Framework) records that say only his server is allowed to send Emails for friend@frienddomain.com, gmail apparently rejects (silently buries actually!) the Email since it is forwarding through my server. Please note that this is exactly what SPF is designed to prevent — spammers from sending Emails with your address — but it breaks forwarding and has other problems.

I also do what the author above talks about, i.e. I forward the email for my various domains to my various Gmail accounts.  Hopefully this is not an issue, that no one who emails directly to my domain email addresses is using SPF.

One proposed solution by a Slashdot poster makes sense, use Google apps.  Fortunately this is available for free on Dreamhost, my web host, and is easy to set up.  I might try it later.

Is there another solution?

Yes, of course. Have all your email sent to Google in the first place! You don’t have to switch everything over to the Google app tool, you can just set MX records for your domain pointing to them, and collect it all (or forward it inside or outside Google.) It’s free (with a paid version available.) Check it out here Smart apps for email, documents, sites and more

Enabling Trace Level Debugging in JBoss

In JBoss 4.0.4.GA it took me awhile to figure out how to enable trace level debugging.

Typically you could do something like this to enable trace level debugging for a category of classes.

<category  name="com.betweengo.app">
  <priority  value="TRACE"/>
</category>

However JBoss 4.0.4.GA has an older log4j implementation so you need to use JBoss’s custom TRACE level.

<category  name="com.betweengo.app">
  <priority  value="TRACE" class="org.jboss.logging.XLevel"/>
</category>

This is documented in the release notes for JBoss-4.2.1.GA.

Since the latest log4j includes a trace level, there is no need to reference the custom jboss TRACE level in conf/jboss-log4j.xml configs, JBAS-4163.

There is additional information on trace level debugging in the articles Enabling TRACE logging on server and Using Logging.

Log SQL on ATG

Dudley Zoo Sarah the Sumatran Tiger (Life Of Pi) on FlickrDudley Zoo Sarah the Sumatran Tiger (Life Of Pi) by donebythehandsofabrokenartist

To log SQL turn on logging debug for your Repository component.

For example, set /betweengo/repository/Repository.loggingDebug to true.

Note that a lot of SQL statements are outputted. If you want to selectively turn it on and off you can put this in your JSP where you want to start logging SQL.

<dspel:setvalue bean="/betweengo/repository/Repository.loggingDebug"  value="true"/>

And then put this in your JSP where you want to stop logging SQL.

<dspel:setvalue bean="/betweengo/repository/Repository.loggingDebug"  value="false"/>

Note I think this solution only works if you are using a javax.sql.DataSource like in a JBoss configuration.

For ATG’s atg.service.jdbc.FakeXADataSource there are special properties for logging SQL.

Property Description
loggingSQLError logs SQL exceptions as errors
loggingSQLWarning logs SQL warnings received by the pool
loggingSQLInfo logs SQL statements sent by the pool
loggingSQLDebug logs JDBC method calls made by the pool

For debugging purposes most of the time you will just want to set loggingSQLInfo=true.

For further reading please see Configuring ATG Data Sources for Data Import in the ATG Installation and Configuration Guide.

Content Repository in ACC

To display a content repository in the ACC it must be listed in the initialRepositories property of the /atg/registry/ContentRepositories component.

For example:

initialRepositories+=\
       /betweengo/repository/Portal

From the ATG Repository Guide > 12. SQL Repository Reference > Configuring the SQL Repository Component > Registering a Content Repository:

Content repositories must be added to the list of repositories in the initialRepositories property of the /atg/registry/ContentRepositories component. This also causes the new repository to show up in the Content window of the ATG Control Center.

ORA-12514 and ORA-27101

This morning I was unable to access my Oracle database which runs on my laptop. It’s the first time I have had this problem.

When I tried to login I saw this.

$ sqlplus foo/foo@dev01

SQL*Plus: Release 10.2.0.1.0 - Production on Thu Jul 3 06:38:20 2008

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

ERROR:
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor

When I tried to login without the TNS alias I saw this:

$ sqlplus foo/foo

SQL*Plus: Release 10.2.0.1.0 - Production on Thu Jul 3 06:38:20 2008

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

ERROR:
ORA-01034: ORACLE not available
ORA-27101: shared memory realm does not exist

On the internet I saw recommendations to set your ORACLE_SID and ORACLE_HOME environment variables. But on my system ORACLE_SID is not set and ORACLE_HOME is blank. Finally I just tried restarting the OracleServiceDEV01 service and that worked.

SQL Update in One Table Based on Values in Another Table

Dolphin Crest on Flickr

(Photo: Dolphin Crest by jurvetson)

I was wondering how to do this and thankfully someone wrote up a nice article on the SQL update statement.

Here is their example of how to do this.

UPDATE suppliers
SET name =
  ( SELECT customers.name
  FROM customers
  WHERE customers.id = suppliers.id)
WHERE EXISTS
  ( SELECT customers.name
  FROM customers
  WHERE customers.id = suppliers.id);

Merge Adobe PDF files

I was looking for a program that would merge Adobe PDF files.  At first I found this trial program, A-PDF Merger, which worked fine but left a small watermark on the first page.  Then I found this open source program, PDF Split and Merge, which did the trick but the UI is kind of slow, possibly because it is written in Java.  It looks like there are plenty of other free programs available too.

How Facebook Stores Billions of Photos

Those guys at Facebook sure are smart. Here is an online presentation titled Needle in a Haystack: Efficient Storage of Billions of Photos.

Jason Sobel, the manager of infrastructure engineering at Facebook, … explains how Facebook efficiently stores ~6.5 billion images, in 4 or 5 sizes each, totaling ~30 billion files, and a total of 540 TB and serving 475,000 images per second at peak.

Slashdot | How Facebook Stores Billions of Photos