November 6, 2011

How to set Wicket up with Tomcat

The Wicket quickstart project is great, but it can be confusing to progress from that embedded Jetty server to Tomcat (or any other more stable setup), especially if it's your first time setting up a web application. Here's how to make it happen using nothing but ant. (If you can't get the quickstart project working, see my earlier post first.)

The first step is making sure you have all your tools. You're going to need recent versions of both Tomcat and Apache ant already installed.

Just as important as your tools is your directory structure. There is some room for individuality here, but the structure I'm going to show you follows fairly standard conventions. I didn't include version numbers with the JAR files because they'll probably have changed by the time you read this anyways.

\WicketTomcat
  +---src
  | +---main
  | | +---java
  | | | \---com
  | | |   \---HelloWicket
  | | |         HelloWorld.java
  | | |         HelloWorld.html
  | | |         HelloWorldApplication.java
  | | \---webapp
  | |   \---WEB-INF
  | |         web.xml
  | \---test
  |   \---java
  +---lib
  |     junit.jar
  |     log4j.jar
  |     servlet-api.jar
  |     slf4j-api.jar
  |     slf4j-log4j.jar
  |     wicket.jar
  |     wicket-extensions.jar
  +---target
    build.xml

Now that you have all the pieces in place, all you have to do is fill in the files' contents. I happened to use Eclipse Indigo, but there is absolutely nothing IDE-specific about these instructions. You can use any IDE or text editor you want.

HelloWorld.java:

package com.HelloWicket;

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;

public class HelloWorld extends WebPage {
public HelloWorld() {
add(new Label("message", "Hello, Wicket!"));
}
}


HelloWorld.html

<html>
<head>
<title>Wicket Tomcat test title</title>
</head>
<body>
<span wicket:id="message">Message goes here</span>
</body>
</html>


HelloWorldApplication.java

package com.HelloWicket;

import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;

public class HelloWorldApplication extends WebApplication {
public HelloWorldApplication() {
}

/**
* @see org.apache.wicket.Application#getHomePage()
*/
@Override
public Class getHomePage() {
return HelloWorld.class;
}
}


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Extremely simple example of deploying Wicket on Tomcat</display-name>
<context-param>
<param-name>configuration</param-name>
<param-value>development</param-value> <!-- Wicket mode (development or deployment) -->
</context-param>
<filter>
<filter-name>HelloWicket</filter-name> <!-- To be used in filter-mapping > filter-name below -->
<filter-class>
org.apache.wicket.protocol.http.WicketFilter
</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>
com.HelloWicket.HelloWorldApplication <!-- Fully qualified name of WebApplication class -->
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HelloWicket</filter-name> <!-- Must match filter > filter-name above -->
<url-pattern>/*</url-pattern> <!-- Take control of all URLs that start with http://localhost:8080/HelloWicket/ -->
</filter-mapping>
</web-app>
<!--
After deploying to Tomcat, access with http://localhost:8080/HelloWicket/.

Source: http://wicket.apache.org/learn/examples/helloworld.html
-->


build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project default="war" name="HelloWicket" basedir=".">
<property name="final.name" value="HelloWicket" />
<property name="src.main.dir" value="src/main/java" />
<property name="src.test.dir" value="src/test/java" />
<property name="src.web.dir" value="src/main/webapp" />
<property name="lib.dir" value="lib" />
<property name="build.dir" value="target" />
<property name="build.main.classes" value="${build.dir}/classes" />
<property name="build.test.classes" value="${build.dir}/test-classes" />
<property name="build.test.reports" value="${build.dir}/test-reports" />
<property name="build.reports.dir" value="${build.dir}/reports" />
<property name="tomcat.dir" value="..\..\..\..\Program Files\Apache Software Foundation\apache-tomcat-7.0.22\webapps" />

<path id="build.classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
</path>
<target name="clean">
<delete dir="${build.dir}" failonerror="false" />
<delete file="${final.name}.war" failonerror="false" />
</target>
<target name="init">
<mkdir dir="${build.dir}" />
</target>
<target name="compile" depends="init">
<mkdir dir="${build.main.classes}" />
<javac destdir="${build.main.classes}" target="1.6" source="1.6" srcdir="${src.main.dir}" classpathref="build.classpath" includeantruntime="false" />
<copy todir="${build.main.classes}">
<fileset dir="${src.main.dir}">
<include name="**/*.*" />
<exclude name="**/*.java" />
</fileset>
</copy>
</target>
<target name="test-compile" depends="compile">
<mkdir dir="${build.test.classes}" />
<javac destdir="${build.test.classes}" target="1.6" source="1.6" srcdir="${src.test.dir}" includeantruntime="false">
<classpath>
<path refid="build.classpath" />
<pathelement path="${build.main.classes}" />
</classpath>
</javac>
<copy todir="${build.test.classes}">
<fileset dir="${src.test.dir}">
<include name="**/*.*" />
<exclude name="**/*.java" />
</fileset>
</copy>
</target>
<target name="test" depends="test-compile">
<mkdir dir="${build.test.reports}" />
<junit dir="./" failureproperty="test.failure" printSummary="yes" fork="true" haltonerror="true">
<sysproperty key="basedir" value="." />
<formatter type="xml" />
<classpath>
<path refid="build.classpath" />
<pathelement path="${build.main.classes}" />
<pathelement path="${build.test.classes}" />
</classpath>
<batchtest todir="${build.test.reports}">
<fileset dir="${src.test.dir}">
<include name="**/*Test*.java" />
</fileset>
</batchtest>
</junit>
<mkdir dir="${build.reports.dir}" />
<junitreport todir="${build.reports.dir}">
<fileset dir="${build.test.reports}">
<include name="TEST-*.xml" />
</fileset>
<report format="frames" todir="${build.reports.dir}" />
</junitreport>
</target>
<target name="war" depends="test">
<war destfile="${build.dir}/${final.name}.war" webxml="${src.web.dir}/WEB-INF/web.xml">
<lib dir="lib">
<include name="wicket*.jar" />
<include name="slf4j*.jar" />
<include name="log4j*.jar" />
<include name="servlet*.jar" />
</lib>
<classes dir="${build.main.classes}" />
<fileset dir="${src.web.dir}">
<include name="**/*" />
<exclude name="**/web.xml" />
</fileset>
</war>
</target>

<target name="deploy" depends="war">
<echo>Deploying .war to local Tomcat</echo>
<copy todir="${tomcat.dir}">
<fileset dir="${build.dir}" includes="${final.name}.war" />
</copy>
</target>
</project>


Simply adjust for your local Tomcat install's webapps directory, and you should be all set!

Sources:
Chapter 15 of Wicket in Action, free to download from the book's website
The Wicket website's quickstart page and Hello World example page

February 10, 2011

Simple sample to create a dynamic flash card layout in Swing

  • Solid white background
  • Two dynamically resizing text fields
  • Buttons have equal width
  • Buttons float to the top, no more weird grid-based spacing issues
  • Text areas are scrollable
  • Starts out small, but window can be adjusted to any reasonable size, even maximized
package migLayoutCenterExpandTest;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import net.miginfocom.swing.MigLayout;

public class Main {
    static JFrame      frame;

    static JPanel      firstPanel;
    static JPanel      secondPanel;

    static JLabel      firstPanelLabel;
    static JButton     firstPanelButton;

    static JTextArea   textArea1;
    static JTextArea   textArea2;
    static JScrollPane textScrollPane1;
    static JScrollPane textScrollPane2;
    static JButton     button1;
    static JButton     button2;
    static JButton     button3;
    static JButton     button4;
    static JButton     button5;
    static JButton     button6;

    /**
     * @param args
     */
    public static void main(String[] args) {
        createObjects();

        setUpFrame();
        setUpFirstPanel();
        setUpSecondPanel();

        frame.getContentPane().add(firstPanel);
        frame.setVisible(true);
    }

    public static void createObjects() {
        frame = new JFrame();

        firstPanel = new JPanel();

        firstPanelLabel = new JLabel("first label");
        firstPanelButton = new JButton("change screens");

        secondPanel = new JPanel();

        textArea1 = new JTextArea("Text area 1");
        textArea2 = new JTextArea("Text area 2");
        textScrollPane1 = new JScrollPane();
        textScrollPane2 = new JScrollPane();
        button1 = new JButton("Button one text");
        button2 = new JButton("Button two text");
        button3 = new JButton("Button three text");
        button4 = new JButton("Button four text");
        button5 = new JButton("Button five text");
        button6 = new JButton("Button six text");
    }

    public static void setUpFrame() {
        frame.setSize(400, 300);

        JPanel contentPane = (JPanel) frame.getContentPane();
        contentPane.setLayout(new MigLayout("align 50% 50%, filly"));
        contentPane.setBackground(Color.WHITE); // Disable this to debug panel sizes

        frame.addWindowListener(new ExitListener());
    }

    public static void setUpFirstPanel() {
        firstPanel.setLayout(new MigLayout("flowy"));
        firstPanel.setBackground(Color.WHITE);

        firstPanel.add(firstPanelLabel, "align 50%");
        firstPanel.add(firstPanelButton, "align 50%");

        firstPanelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Container contentPane = frame.getContentPane();
                contentPane.removeAll(); // Required for new stuff to appear
                contentPane.add(secondPanel); // Required for new stuff to appear; this _is_ the new stuff, after all
                ((JPanel) contentPane).revalidate(); // Required for new stuff to appear
                contentPane.repaint(); // Without this, old stuff isn't removed before new stuff is painted and is still visible underneath
            }
        });
    }

    public static void setUpSecondPanel() {
        secondPanel.setLayout(new MigLayout("fill, flowy"));
        secondPanel.setBackground(Color.WHITE);

        secondPanel.setPreferredSize(new Dimension(1650, 1080));
        secondPanel.setMinimumSize(new Dimension(300, 200));
        secondPanel.setMaximumSize(new Dimension(1920, 1080));

        textScrollPane1 = new JScrollPane(textArea1);
        textScrollPane2 = new JScrollPane(textArea2);

        textScrollPane1.setBackground(Color.WHITE);
        textScrollPane2.setBackground(Color.WHITE);

        textScrollPane1.setBorder(BorderFactory.createTitledBorder("Text area 1"));
        textScrollPane2.setBorder(BorderFactory.createTitledBorder("Text area 2"));

        textScrollPane1.setPreferredSize(new Dimension(400, 300));
        textScrollPane2.setPreferredSize(new Dimension(400, 300));

        // cell col row [span x [span y]]
        secondPanel.add(textScrollPane1, "cell 0 0 1 1, push, grow");
        secondPanel.add(textScrollPane2, "cell 0 1 1 1, push, grow");
        secondPanel.add(button1, "cell 1 0 1 2, aligny top, growx");
        secondPanel.add(button2, "cell 1 0, growx");
        secondPanel.add(button3, "cell 1 0, growx");
        secondPanel.add(button4, "cell 1 0, growx");
        secondPanel.add(button5, "cell 1 0, growx");
        secondPanel.add(button6, "cell 1 0, growx");
    }
}

class ExitListener extends WindowAdapter {
    public void windowClosing(WindowEvent event) {
        System.exit(0);
    }
}

February 4, 2011

Simple sample to replace the contents of a content pane in Swing


package swingTest;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Main
{
static JFrame frame;

static JPanel firstPanel;
static JPanel secondPanel;

static JLabel firstPanelLabel;
static JButton firstPanelButton;

static JLabel secondPanelLabel;

/**
* @param args
*/
public static void main(String[] args)
{
createObjects();

firstPanel.add(firstPanelLabel);
firstPanel.add(firstPanelButton);

firstPanelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
Container contentPane = frame.getContentPane();
contentPane.remove(firstPanel); // Required for new stuff to appear
contentPane.add(secondPanel); // Required for new stuff to appear; this _is_ the new stuff, after all
((JPanel) contentPane).revalidate(); // Required for new stuff to appear
contentPane.repaint(); // Without this, old stuff isn't removed before new stuff is painted and is still visible underneath
}
});

secondPanel.add(secondPanelLabel);

frame.addWindowListener(new ExitListener());
frame.getContentPane().add(firstPanel);
frame.setVisible(true);
}

public static void createObjects()
{
frame = new JFrame();
frame.setSize(500, 500);

firstPanel = new JPanel();
firstPanel.setLayout(new FlowLayout());
firstPanelLabel = new JLabel("first label");
firstPanelButton = new JButton("first button");

secondPanel = new JPanel();
secondPanel.setLayout(new FlowLayout());
secondPanelLabel = new JLabel("second label");
}
}

class ExitListener extends WindowAdapter
{
public void windowClosing(WindowEvent event)
{
System.exit(0);
}
}

December 3, 2010

Wicket installation

Update: I finally got around to writing the second part, about setting Wicket up with Tomcat instead of relying solely on the embedded Jetty server. See it here.


Downloaded JDK 6_22
Downloaded Maven 3.01
Installed JDK to C:\Program Files\Java\jdk1.6.0_22
Unzipped maven to C:\Program Files\apache-maven-3.0.1
Updated system environment variables:

- M2
C:\Program Files\apache-maven-3.0.1
- M2_HOME
%M2_HOME%\bin = C:\Program Files\apache-maven-3.0.1\bin
- JAVA_HOME
C:\Program Files\Java\jdk1.6.0_22
- M2_REPO
C:\Users\Programmer\.m2\repository

Followed instructions at Wicket quickstart
Generated this Maven command from quickstart:

mvn archetype:create -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.4.1 -DgroupId=com.mycompany -DartifactId=projName

Ran above Maven command from command line
Relevant files, including Wicket source, were downloaded automatically (based on POM?)
Ran mvn eclipse:eclipse to create an Eclipse project based on above
Imported project into Eclipse with File > Import..., Existing Projects

Ran Start.java in the test folder and went to http://localhost:8080 — success.

Wanted to add Wicket Extensions support.
Manually adding JAR file to to M2_REPO directory didn't work.

Current status:
Adding a dependency to the POM is probably right (there's even a similar dependency in there but commented out), but how will Maven understand that the new dependency needs to be added? Merely uncommenting and running Start does nothing.

Resolved: Just run mvn clean dependency:copy-dependencies after updating the POM. There's probably a better way to do this, though. Then configure the build path by using Add Variables... (not Add JARs), select M2_REPO, press Extend, find the desired JAR (in this case, Wicket Extensions).

Current status:
Need to figure out how to make this worth with Tomcat instead of relying on the embedded Jetty server all the time.

August 23, 2010

Why arrow code is bad

I, like Jeff Atwood, don't like arrow code.

But is arrow code actually bad, or just unsightly? It's bad. Jeff mentions cyclomatic complexity but doesn't describe it; so see Wikipedia.

In particular,

[Most of the relevant] studies find a strong positive correlation between cyclomatic complexity and defects: modules that have the highest complexity tend to also contain the most defects.

August 10, 2010

How Ryan Tomayko explained REST to his wife

The web is built on an architectural style called REST. REST provides a definition of a resource, which is what [URLs] point to.

A web page is a representation of a resource. Resources are just concepts. [URLs] tell the browser that there’s a concept somewhere. A browser can then go ask for a specific representation of the concept. Specifically, the browser asks for the web page representation of the concept.

Full post on Ryan's blog

July 13, 2010

Vista fonts compared to older fonts

The "Vista fonts" are Cambria, Calibri, Candara, Consolas, Constantia and Corbel. A good piece on them is provided by hunlock.com here.

July 12, 2010

Package becomes unrecognized in Eclipse

Error:
Saving a Java source file in Eclipse causes the errors "[class] cannot be resolved to a type" and "The import org.oasis_open.docs.[whatever] cannot be resolved" for classes in a package that was previously recognized.

Solution:
Open the context menu for the affected package in Package Explorer, select Build Path > Configure Build Path... and go to the "Order and Export" tab. Make sure custom classes are at the top, third-party files are in the middle and the JRE is at the bottom of the list. Select OK and refresh the affected files/packages.

July 8, 2010

Putting a head tag below a body tag

It is possible to put <head> tags underneath <body> tags. Why do this? One reason is to make cache instructions work better, as described by Microsoft here.

Another is described in High Performance Web Sites: Rule 6 – Move Scripts to the Bottom by Steve Souders, Yahoo!'s Chief Performance Yahoo!

With stylesheets, progressive rendering is blocked until all stylesheets have been downloaded. That’s why it’s best to move stylesheets to the document HEAD, so they get downloaded first and rendering isn’t blocked. With scripts, progressive rendering is blocked for all content below the script. Moving scripts as low in the page as possible means there's more content above the script that is rendered sooner.

The second problem caused by scripts is blocking parallel downloads.

July 6, 2010

The Java heap

The young generation consists of eden plus two survivor spaces. Objects are initially allocated in eden. One survivor space is empty at any time, and serves as a destination of the next, copying collection of any live objects in eden and the other survivor space. Objects are copied between survivor spaces in this way until they are old enough to be tenured, or copied to the tenured generation.

-Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine by Sun

The Java HotSpot VM defines two generations: the young generation (sometimes called the "nursery") and the old generation. The young generation consists of an "Eden space" and two "survivor spaces." The VM initially assigns all objects to the Eden space, and most objects die there. When it performs a minor GC, the VM moves any remaining objects from the Eden space to one of the survivor spaces. The VM moves objects that live long enough in the survivor spaces to the "tenured" space in the old generation. When the tenured generation fills up, there is a full GC that is often much slower because it involves all live objects. The permanent generation holds all the reflective data of the virtual machine itself, such as class and method objects.

-Using JConsole by Sun

See figure at either link above (both use the same figure).

Mark-and-Sweep Garbage Collection, used in Tenured Generation GC
Stop-and-Copy Garbage Collection, used in Young Generation GC
The Copy Algorithm, used in the Stop-and-Copy method of GC

June 28, 2010

Create and print a simple XML document in Java using javax.xml.transform.Transformer


package pkg;

import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Bar
{
public static void main(String[] args)
{
List properties = new ArrayList();
properties.add(new DummyObject("n1", "t1", "v1"));
properties.add(new DummyObject("n2", "t2", "v2"));
properties.add(new DummyObject("n3", "t3", "v3"));
properties.add(new DummyObject("n4", "t4", "v4"));
properties.add(new DummyObject("n5", "t5", "v5"));
properties.add(new DummyObject("n6", "t6", "v6"));
properties.add(new DummyObject("n7", "t7", "v7"));
properties.add(new DummyObject("n8", "t8", "v8"));
properties.add(new DummyObject("n9", "t9", "v9"));

// Create XML document tree
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
Document documentTree = null;
Element dummyParent = null;
try
{
db = dbf.newDocumentBuilder();
documentTree = db.newDocument();
dummyParent = documentTree.createElement("DummyParent");
documentTree.appendChild(dummyParent);

for (DummyObject property : properties)
{
// Create XML tags for the property
Element propertyNode = documentTree.createElement("Property");
Element nameNode = documentTree.createElement("Name");
Element typeNode = documentTree.createElement("Type");
Element valueNode = documentTree.createElement("Value");

// Populate the property's XML tags
nameNode.setTextContent(property.getName());
typeNode.setTextContent(property.getType());
valueNode.setTextContent(property.getValue());

// Add the data to the property node
propertyNode.appendChild(nameNode);
propertyNode.appendChild(typeNode);
propertyNode.appendChild(valueNode);

// Add the property node to the XML tree
dummyParent.appendChild(propertyNode);
}

DOMSource source = new DOMSource(documentTree);
StreamResult result = new StreamResult(System.out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(source, result);
}
catch (ParserConfigurationException e)
{
System.out.println("D'oh! Creating the document failed.");
System.out.println(e.getMessage());
}
catch (TransformerException e)
{
System.out.println("D'oh! Transformer failed.");
System.out.println(e.getMessage());
}
}
}

class DummyObject
{
String name;
String type;
String value;

public DummyObject()
{
super();
}

public DummyObject(String n, String t, String v)
{
name = n;
type = t;
value = v;
}

public String getName()
{
return name;
}

public String getType()
{
return type;
}

public String getValue()
{
return value;
}
}

June 1, 2010

[Tom] Duff's Device

Duff's Device is mentioned in the JLS section about switch statements. The nitty-gritty is explained at this StackOverflow answer.

Sample code:

package pkg;

public class Foo
{
public static void main(String args[])
{
int numTimesToCallMethod = 20;
int numTimesToRunWhile = (numTimesToCallMethod + 7) / 8;

switch (numTimesToCallMethod%8)
{
case 0:
do {
IllHaveADuffYouHaveOneToo(); // Great C hack, Tom,
case 7: IllHaveADuffYouHaveOneToo(); // but it's not valid here.
case 6: IllHaveADuffYouHaveOneToo();
case 5: IllHaveADuffYouHaveOneToo();
case 4: IllHaveADuffYouHaveOneToo();
case 3: IllHaveADuffYouHaveOneToo();
case 2: IllHaveADuffYouHaveOneToo();
case 1: IllHaveADuffYouHaveOneToo();
} while (--numTimesToRunWhile > 0);
}
}

public static void IllHaveADuffYouHaveOneToo()
{
System.out.println();
}
}


MyEclipse 8.5 shows two errors at the semicolon immediately before "Great C hack...":
Multiple markers at this line
- Syntax error, insert "while ( Expression ) ;" to complete DoStatement
- Syntax error, insert "}" to complete Block

April 28, 2010

CMIS notepad

CMIS 1.0 specification (HTML):
http://docs.oasis-open.org/cmis/CMIS/v1.0/cs01/cmis-spec-v1.0.html

CMIS Relationship object:
http://docs.oasis-open.org/cmis/CMIS/v1.0/cs01/cmis-spec-v1.0.html#_Toc243905402

CMIS Relationship Service:
http://docs.oasis-open.org/cmis/CMIS/v1.0/cs01/cmis-spec-v1.0.html#_Toc243905479

The Relationship Services (getObjectRelationships) are used to retrieve the dependent Relationship objects associated with an independent object.

April 21, 2010

Weak references in Java

there are actually four different degrees of reference strength: strong, soft, weak, and phantom

The important part about strong references — the part that makes them "strong" — is how they interact with the garbage collector. Specifically, if an object is reachable via a chain of strong references (strongly reachable), it is not eligible for garbage collection.

A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory.

Understanding Weak References by Ethan Nicholas

April 13, 2010

Show/hide .classpath and other files in Eclipse Package Explorer

Click on the down arrow icon at the top of the toolbar, and open the Filters menu.

Firebug does not reload JavaScript properly

Workaround is to clear all breakpoints in the JavaScript file and Shift+F5 or Shift+reload the page.

See Firebug issue 207.

March 30, 2010

XML namespaces intro

XML:
Simple example without schema involvement
FILL IN

XML Schema:
targetNamespace

"targetNamespace is used in a schema to specify the namespace that the schema is intended to define" -David Peterson, at JavaRanch

"Each schema document has exactly one target namespace." -XML in a Nutshell

default namespace

noNamespaceSchemaLocation
noNamespaceSchemaLocation: schema to reference for elements that have no namespace prefix?
"The noNamespaceSchemaLocation attribute references an XML Schema document that does not have a target namespace. "

schemaLocation

Interface between XML document and its schema:
FILL IN

Note from w3schools:
The namespace URI is not used by the parser to look up information.

The purpose is to give the namespace a unique name. However, often companies use the namespace as a pointer to a web page containing namespace information.

March 16, 2010

Getting started with Groovy

http://docs.codehaus.org/display/GROOVY/Install+Groovy-Eclipse+Plugin
http://docs.codehaus.org/display/GROOVY/Create+Your+First+Groovy+Project

CSS positioning

http://stackoverflow.com/questions/2451043/change-an-absolutely-positioned-webpage-into-a-centered-one/2451067#2451067

FINISH POST