Tuesday, December 14, 2010

Install Certs

No more 'unable to find valid certification path to requested target'

Some of you may be familiar with the (not very user friendly) exception message

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

when trying to open an SSL connection to a host using JSSE. What this usually means is that the server is using a test certificate (possibly generated using keytool) rather than a certificate from a well known commercial Certification Authority such as Verisign or GoDaddy. Web browsers display warning dialogs in this case, but since JSSE cannot assume an interactive user is present it just throws an exception by default.

Certificate validation is a very important part of SSL security, but I am not writing this entry to explain the details. If you are interested, you can start by reading the Wikipedia blurb. I am writing this entry to show a simple way to talk to that host with the test certificate, if you really want to.

Basically, you want to add the server's certificate to the KeyStore with your trusted certificates. There are any number of ways to achieve that, but a simple solution is to compile and run the attached program as java InstallCert hostname, for example % java InstallCert ecc.fedora.redhat.com Loading KeyStore /usr/jdk/instances/jdk1.5.0/jre/lib/security/cacerts... Opening connection to ecc.fedora.redhat.com:443... Starting SSL handshake...

Note the source code in the article is WRONG. See below for correct source.

http://blogs.sun.com/andreas/entry/no_more_unable_to_find

Here's the correct source:

Friday, December 10, 2010

Hibernate setParameterList nudge the data type

OK, I've run into this before so I thought I would write it down this time. You do a sql query for a list of ids and they come back as big integers, but really in your object they are longs. So when you go to use the list as a parameter it will complain. However, if you do setParameterList("ids", ids, Hibernate.BIG_INTEGER) it doesn't complain. Sort of counter intuitive to me because your object id is a long. But I guess what you are telling it is what the stuff in the param list is? Whatever, it works. 

Collection<Long> ids = new ArrayList<Long>();

if (!frm.getRygs().isEmpty()) {
    Collection<Long> rygIds = reportDao
            .getSession()
            .createSQLQuery(
                    "select u.id from av_user "
                            + " u left join av_contribution c on u.contribid = c.id "
                            + " where c.redyellowgreen in (:rygs);")
            .setParameterList("rygs", toStringList(frm.getRygs()))
            .list();
    ids.addAll(rygIds);
}

if (!ids.isEmpty()) {
    List<User> users = reportDao.getSession().createQuery(
            "from User where id in (:ids) order by lastName")
            .setParameterList("ids", ids, Hibernate.BIG_INTEGER).list();

Google Refine

Amazing way to clean up messy data. Kudos to JC Mann for the heads up.

http://code.google.com/p/google-refine/

Monday, December 6, 2010

mac os x 10.5 vpn client

So MAC does have a built in PPTP client.

Creating a VPN connection for Mac OS X 10.5 Leopard

1. Click on System Preferences in the apple menu.

2. Click on the Network icon.

3. If the lock icon looks “locked”, click on it and type in your Administrator Name and password.

4. Click on the button at the bottom of the list panel to add a new service (Located just above the Lock).

5. Select VPN in the Interface drop down menu.

Friday, December 3, 2010

Common Hibernate column annotations

Common Hibernate annotations we use for PostgreSQL

@Column(name = "roomSetup", nullable = false, columnDefinition = "character varying(100) default ''")
public String getRoomSetup() {

@Column(name = "endTime")
@org.hibernate.annotations.Type(type = "org.joda.time.contrib.hibernate.PersistentLocalDateTime")
public LocalDateTime getEndTime() {

@Column(name = "incDueDate", nullable = false, columnDefinition = "integer default 0")
public int getIncrementDueDate() {

@Column(name = "aviUpdateDate")
@org.hibernate.annotations.Type(type = "org.joda.time.contrib.hibernate.PersistentLocalDate")
public LocalDate getAviUpdateDate() {

@Column(name = "reservationId", nullable = false, columnDefinition = "bigint default 0")
public long getReservationId() {

@Column(name = "deleted", nullable = false, columnDefinition = "bool default false")
public boolean isDeleted() {

@Column(name = "time")
@org.hibernate.annotations.Type(type = "org.joda.time.contrib.hibernate.PersistentLocalTimeExact")
public LocalTime getDueTime() {

@Column(name = "price", nullable = false, columnDefinition = "double precision default 0")
public double getPrice() {

@Column(name = "unitPrice", nullable = false, columnDefinition = "real default 0")
float unitPrice;

Friday, November 12, 2010

JSP tag files and dynamic attributes

In a JSP tag file sometimes you need to test for the presence of an attribute rather than whether it's empty or not. I needed to know if the id attribute was specified even if the value was empty (""). This is because with Spring's form tags, if you pass any id at all, it uses what you passed even if it's empty, otherwise it generates its own id.

My entire tag file was more complicated than what's below, but this gives you the parts you need to know.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="frm" uri="http://www.springframework.org/tags/form"%>

<%@ tag dynamic-attributes="columnMap"%>

<c:set var="hasId" value="false" />
<c:forEach var="attr" items="${columnMap}">
    <c:if test="${attr.key eq 'id'}"><c:set var="hasId" value="true" /></c:if>
</c:forEach>

<c:if test="${hasId eq true}">
    <frm:input id="${columnMap.id}" />
</c:if>

Remove from wrapped set

Late breaking news. Ugh! Turns out that Set<String> ts = new TreeSet<String>(s) doesn't wrap (thanks rbohn). Not sure why I had it in my head that it did. It creates another Set that contains the elements from the first. That would explain it. It's kind of hard to get anywhere when your presuppositions are wrong!

===========================================================

If you wrap a set with something else TreeSet or ArrayList, etc. Then you iterate over the wrapped collection and call remove on the iterator your item will not be removed. How did I not know this? Have I forgotten? Did I never know?

public static void main(String[] args) {
    Set<String> s = new HashSet<String>();
    s.add("this");
    s.add("that");
    s.add("momma");
    Set<String> ts = new TreeSet<String>(s);
    for (Iterator<String> it = ts.iterator(); it.hasNext();) {
        String ss = it.next();
        if ("momma".equals(ss)) {
            it.remove();
        }
    }
    System.out.println(s);
}

The output of the above will be as shown below (in no specific order). Yo momma did not get removed.

[that, momma, this]

Monday, November 8, 2010

Prevent double click

This is the only bulletproof way I know to prevent double clicks. The onclick event has to disable itself. You can't do "onclick='void 0;' in a function that you call from onclick because you may have already clicked three times before that function gets called.

For buttons, just do the onclick.
<input type="button" onclick="this.onclick='void 0;';someFunction();" />

For links you also have to explicitly do nothing in the href. Don't do href="#". That will not work.
<a href="javascript:void 0;" onclick="this.onclick='void 0;';someFunction();">

OK, rbohn says the following also works. If you want to separate all the logic into a single function, you can as long as the function returns false and your onclick returns false. For example: onclick="return myFunc(this);" Also, you must use el.setAttribute and not el.onclick=. el.onclick= will work in some browsers, but not others.

Another nice thing about rbohn's way is that your href can be set to # which is a bit neater. OK, well in a nicely controlled environment, with rbohn's way you can set your href to #, but in the real messy world, you need to have it set to "javascript:void 0;" or "javascript:return 0;". I have seen it break when set to #.

function myFunc(el) {
    el.setAttribute('onclick','return false;');
    document.forms['aviForm'].submit();  
    return false;
}

<a href="javascript:void 0;" onclick="return myFunc(this);">Confirm</a>

<input type="button" onclick="return myFunc(this);" />

Tuesday, November 2, 2010

Hibernate mapping cheat sheet

Check list

1. Make sure Collections are initialized.
2. Make sure Collections can't be null.
3. Most names and some other fields should not be null.

@Entity
@Table(name = "ar_campus")
public class Campus . . .

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;

    @Column(name = "xxx")
    @Column(name = "xxx", length = 11, unique = true, nullable = false)
    String someColumn;

Join column name has this rule: "Single same name as property, set name of parent"

Child NO reference back to parent.

class Hand {
    @OneToMany
    @JoinColumn(name = "handid")
    Set<Finger> fingers;

Child HAS reference back to parent.

class Hand {
    @OneToMany(mappedBy = "hand")
    Set<Finger> fingers;
  
class Finger {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "handid")
    Hand hand;

One to one with join column:

class Organization {
    @OneToOne(optional = false, mappedBy = "organization")
    OrgBoardInfo boardInfo;

class BoardInfo {
    @OneToOne(optional = false)
    @JoinColumn(name = "orgid", unique = true, nullable = false, updatable = false)
    Organization organization;

One to one with shared key:

class User {
    @OneToOne()
    @PrimaryKeyJoinColumn
    public AuxInfo auxInfo;

class AuxInfo {
    //(note must NOT put @GeneratedValue annotation on id)
    @Id
    Long    id;

    @OneToOne()
    @PrimaryKeyJoinColumn
    User    user;

Built in Java classes (String, Date, Long) or custom element.

class Board {
    @Enumerated(EnumType.STRING)
    @Column(name = "type")
    public BoardType type;

class Campus {
    @Column(name = "holiday", nullable = false)
    @CollectionOfElements(targetElement = PersistentLocalDate.class)
    @JoinTable(name = "ar_campus_holiday", joinColumns = { @JoinColumn(name = "cid") })
    Set<LocalDate> holidays;

class User {
    @Column(name = "system", nullable = false)
    @CollectionOfElements
    @Enumerated(EnumType.STRING)
    @JoinTable(name = "user_desired_system", joinColumns = @JoinColumn(name = "user"))
    Set<ExternalSystem> desiredSystems;

class Reservation {
    @ManyToMany
    @JoinTable(name = "rez_sr", joinColumns = { @JoinColumn(name = "rezId") }, inverseJoinColumns = { @JoinColumn(name = "srId") })
    Set<SubReceipt> subReceipts;

Column specs (for postgresql)

    @Column(name = "yearsOfExperience", nullable = false, columnDefinition = "integer default 0")
    int            yearsOfExperience;

    @Column(name = "experience", nullable = false, columnDefinition = "character varying(5000) default ''")
    String        experience;

    @Column(name = "deleted", nullable = false, columnDefinition = "bool default false")
    boolean deleted;

    @Column(name = "reservationId", nullable = false, columnDefinition = "bigint default 0")
    long reservationId;

Friday, October 15, 2010

Change field/column size in postgresql

Size will be value -4, so add 4 to whatever number you want.

update pg_attribute
set atttypmod = 2048
where attrelid = (
select oid
from pg_class
where relname = 'av_payment_transaction' )
and attname = 'solomonstatusmessage';

thanks to