Available categories: [/] [Technology]
|
Why Tab Indentation is Evil [Permalink] Tue Dec 11 16:48:32 EST 2007 Tab indentation is Wrong. I know this instinctively, but from time to time I forget the actual proof of this and go looking around on the interwebs, only to find a bunch of religious-warlike opinions that are mostly subjective. Yesterday I remembered the Real Reason why tab indentation is objectively horrible. Here we go: tab stops differ between systems, so tab indentation is shown with varying amounts of white space, depending on the system on which the file is displayed. In order to properly indent code, one sometimes (often) needs to indent to a position that does not fall on a tab stop. One example is this:
public Person findPerson(String firstName,
String lastName,
String zipCode);
In order to line up the arguments with the open paren, an editor using tab indentation is then forced to use a combination of tabs and spaces that is correct only when viewed with tab stops set to the same increment as that on the computer creating the file, thus making the argument that different people viewing code on different machines can use indentation steps to their liking completely invalid. Tab indentation is simply broken for code such as this. I just don't understand why an editor like Eclipse would make tab indentation the default. I've seen so much unreadable code as a direct result of this, it's not funny. Please! For the sake of good taste and human decency, stop using tab indentation! Thank you.
Chasing Methods With Interfaces in Eclipse [Permalink] Wed Jan 24 20:19:43 EST 2007 Back in the days when I was doing software development full time for one company, we had a few arguments about the relative merits of designing by interface. The product we happened to work on had almost certainly overused interfaces, with nearly a 1:1 relationship of interface to class. It didn't help that they named things horribly, calling the interfaces along the lines of Anyway, one of the main objections to using interfaces when you only have one implementation of an object is that it makes code much more difficult to trace in Eclipse, since when you control-click the method name, Eclipse goes to the interface instead of the object you're looking for. This means you'd have to separately find the implementer of that class, then navigate to that class, remembering which method you were trying to trace, then navigate to the method. Today I learned an easier way. To trace a method through to its implementer from a call on an interface, simply click on the method (no need to highlight, as long as the cursor is in the method name) and type control-t. This will display the type hierarchy of the interface on the page, and then you can down arrow to the implementing classes and hit return. Eclipse will take you to the right method in the implementing class. It's still one step more difficult than just control-clicking, but effectively makes it almost trivial to trace methods, even through calls on an interface. Fun with Linux Routing [Permalink] Sat May 20 21:49:25 EDT 2006 I tried running the import program for my photo application today, which parses an XML file with a DTD. It failed with "java.net.ConnectException: Connection refused." This was a bit baffling to me, since the DTD in the document was hosted on the same server that I was running the program. A quick check with netcat confirmed that, in fact, connections were being refused on port 80 to the same host. Even more baffling was that I was still serving web requests to outside hosts with no trouble. Anyway, to make a long story short, the trouble turned out to be in my routing configuration, which is setup to redirect port 80 to port 8080 and port 443 to 8443 so that I can run Resin as an unprivileged user while still responding to requests on port 80. I had never paid particular attention to the specifics of the common advice I had found on the web (I think in Caucho's documentation, actually) except to note that it worked. My previous routing rules were these:
iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j REDIRECT --to-port 8080 -d 66.92.72.224
iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j REDIRECT --to-port 8080 -d 66.92.72.225
iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth1 -j REDIRECT --to-port 8080 -d 66.92.72.224
iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth1 -j REDIRECT --to-port 8080 -d 66.92.72.225
iptables -t nat -A PREROUTING -p tcp --dport 443 -i eth0 -j REDIRECT --to-port 8443 -d 66.92.72.224
iptables -t nat -A PREROUTING -p tcp --dport 443 -i eth0 -j REDIRECT --to-port 8443 -d 66.92.72.225
iptables -t nat -A PREROUTING -p tcp --dport 443 -i eth1 -j REDIRECT --to-port 8443 -d 66.92.72.224
iptables -t nat -A PREROUTING -p tcp --dport 443 -i eth1 -j REDIRECT --to-port 8443 -d 66.92.72.225
There are two problems with this. First, the PREROUTING chain seems only to affect packets actually routed by the box, so not locally originated packets. I fixed this by adding a set of similar rules in the OUTPUT chain, which affects packets before routing. From the
nat:
This table is consulted when a packet that creates a new
connection is encountered. It consists of three built-ins:
PREROUTING (for altering packets as soon as they come in),
OUTPUT (for altering locally-generated packets before rout‐
ing), and POSTROUTING (for altering packets as they are
about to go out).
The new lines looked like this:
iptables -t nat -A OUTPUT -p tcp --dport 80 -i eth0 -j REDIRECT --to-port 8080 -d 66.92.72.224
iptables -t nat -A OUTPUT -p tcp --dport 80 -i eth0 -j REDIRECT --to-port 8080 -d 66.92.72.225
iptables -t nat -A OUTPUT -p tcp --dport 80 -i eth1 -j REDIRECT --to-port 8080 -d 66.92.72.224
iptables -t nat -A OUTPUT -p tcp --dport 80 -i eth1 -j REDIRECT --to-port 8080 -d 66.92.72.225
iptables -t nat -A OUTPUT -p tcp --dport 443 -i eth0 -j REDIRECT --to-port 8443 -d 66.92.72.224
iptables -t nat -A OUTPUT -p tcp --dport 443 -i eth0 -j REDIRECT --to-port 8443 -d 66.92.72.225
iptables -t nat -A OUTPUT -p tcp --dport 443 -i eth1 -j REDIRECT --to-port 8443 -d 66.92.72.224
iptables -t nat -A OUTPUT -p tcp --dport 443 -i eth1 -j REDIRECT --to-port 8443 -d 66.92.72.225
I loaded the rules and in my testing discovered that the host configured on my second IP address, 66.92.72.225, was coming up with the content from the first IP, trailmagic.com, in my browser. I looked over the rules a few more times and, resorting to the man page once again, discovered that the REDIRECT target "redirects the packet to the machine itself by changing the destination IP to the primary address of the incoming interface." Clearly not what I wanted, since I've got two interfaces in this machine and one virtual interface, each configured with a different IP address. A little more studying turned up the DNAT target, which does exactly what I want (and thought REDIRECT was doing earlier). This probably explains why the commonly-recommended rules seem to work for most people, and are still working on my development machine, namely that most people don't have more than one interface, so it doesn't matter that REDIRECT only uses the primary interface. My final rules look like this:
iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j DNAT --to-destination 66.92.72.224:8080 -d 66.92.72.224
iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j DNAT --to-destination 66.92.72.225:8080 -d 66.92.72.225
iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth1 -j DNAT --to-destination 66.92.72.224:8080 -d 66.92.72.224
iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth1 -j DNAT --to-destination 66.92.72.225:8080 -d 66.92.72.225
iptables -t nat -A PREROUTING -p tcp --dport 443 -i eth0 -j DNAT --to-destination 66.92.72.224:8443 -d 66.92.72.224
iptables -t nat -A PREROUTING -p tcp --dport 443 -i eth0 -j DNAT --to-destination 66.92.72.225:8443 -d 66.92.72.225
iptables -t nat -A PREROUTING -p tcp --dport 443 -i eth1 -j DNAT --to-destination 66.92.72.224:8443 -d 66.92.72.224
iptables -t nat -A PREROUTING -p tcp --dport 443 -i eth1 -j DNAT --to-destination 66.92.72.225:8443 -d 66.92.72.225
# for local packets
iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination 66.92.72.224:8080 -d 66.92.72.224
iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination 66.92.72.225:8080 -d 66.92.72.225
iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 66.92.72.224:8443 -d 66.92.72.224
iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 66.92.72.225:8443 -d 66.92.72.225
The DNAT target takes a Maven Repository for Ant [Permalink] Sat Mar 04 19:56:13 EST 2006 I recently discovered that the Maven Project has made available some of its tasks for Ant. I've noted previously that Maven's repository feature is quite nice, although I haven't been as attracted to the system as a whole, so this is a great development for those of us using Ant for our build systems. I'll definitely be thinking about integrating this into the build systems I use if I ever get a bit of free time. On Java Web Start and Browsers [Permalink] Fri Mar 03 17:24:41 EST 2006 I've been playing around with a few Java Web Start applications lately (most notably the excellent BlogBridge, which I'll likely write about at some point in the future), and one problem I ran into was that, when I clicked on a link to launch in a browser, the link would opoen in the wrong browser. Once I figured out that I could run Now, I could froth and foam about how many ways this behavior is wrong on the part of Web Start, mainly having to do with ignoring both my GNOME preference for Firefox and my Firefox preference to never open new windows, but I'll spare you my fury. Instead, I'll pass on the workaround I found to solve it. A little bit of searching let me to the conclusion that one can set a property in the deployment.browser.args=%u
The Spring Confusion [Permalink] Thu Dec 29 14:27:21 EST 2005 I spent about 6 hours yesterday trying to build a simple utility for my photo software that would replace an image in the database with an image from a file. I was using Spring to manage Hibernate sessions using a First, I added debugging statements to my code, which showed that when I was getting my bean from the ApplicationContext, my property setter was being called with a valid object, but the value of the field was
<bean id="hibernateInterceptor"
class="org.springframework.orm.hibernate.HibernateInterceptor">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<bean id="replaceImageManifestation"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<bean
class="com.trailmagic.image.util.ReplaceImageManifestation">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
</property>
<property name="interceptorNames">
<list>
<value>hibernateInterceptor</value>
</list>
</property>
</bean>
I ended up modifying the configuration to the following, which essentially does the same thing, but also declaratively manages transactions for me:
<bean id="replaceImageManifestation"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="transactionManager"/>
</property>
<property name="target">
<ref local="replaceImageManifestationTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="replace*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="replaceImageManifestationTarget"
class="com.trailmagic.image.util.ReplaceImageManifestation">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
<property name="imageManifestationFactory">
<ref local="imageManifestationFactory"/>
</property>
</bean>
Either configuration should work, and I still have beans using the former configuration. The problem was only in the method protection. Now it all works fine, and I know that next time I'll turn on the full debug logging sooner, although it can be hard to parse with all the extra output. Lessons learned:
Java Session Management Is Broken [Permalink] Tue Aug 23 20:01:27 EDT 2005 I just got burned by this while posting the last blog entry, and it's something that's annoyed me for a long time. It's a little unfair to say that Java's session management is broken, I suppose. The problem is more in the way people use it. Here's the common problem: a site has a form that takes a long time to fill out, such as a field for text that might take a long time to compose. Some people, like me, tend to start filling out a form (or composing a comment, blog entry, etc.), then shift to other work, leaving the form half-filled for hours, maybe days. In the meantime, the server-side session times out, and when the user goes to submit the form, the server simply sends back a login page, blissfully ignoring your carefully entered form data. Now, the first thing wrong with this is that the session times out. It's entirely possible to never stick information needed for things like form submission in a session object. Granted, Java makes it really easy to stick things in a session and get them back out, which is why people use them so much, but it's not that hard to stick things in a database instead, or in hidden fields within the page. My real complaint with Java is that it doesn't make it easier to make persistent sessions. Failing the use of a persistent session, a good web developer should work around this problem. There are several possibilities: a login page could forward I just wish Java made it easier to Do The Right Thing. |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Available categories: [/] [Technology]
html hits: 67887