Thursday, January 17, 2008
When is a Constant not a Constant?
Oh, sure, you can declare a final object. What that means is that you can't change the reference. But values are up for grabs.
I wonder how many people this has torched in the past?
Thank god for SCJP where I learned that final is not final as in primitives final but somewhat less final than you would sometimes want.
I guess the next thing to find out is how you keep an object from changing its values (or rather, guarantee that it can't).
And final doesn't always mean the same thing. Final in a primitive means you can't change the value. Final in an object means you can't change the reference. Final in a method means that you can't override the method on inheritance. Final in a class means you can't inherit from it at all.
Interesting rules, and it doesn't seem like final is ever misused but it can be confusing. At least to me, anyway.
Powered by ScribeFire.
Thursday, June 21, 2007
Adding Rows Dynamically
So, if you're creating a table, it goes something like this:
<table>
<tbody>
<tr>
<td> Something here </td>
<td> Something else here</td>
</tr>
</tbody>
</table>
Right? (note: tbody seems to be required for this by ie)
So, if you want to add a row to this, all dynamic-like, the first thing to do is add an ID to the tbody (since that's the element you'll actually be adding to)
<tbody id="tbody">
Then you can add a control to your page to add the row. Something like
<input type="button" value="Add Row" />
So, aside from the rest of the page declaration (<html><head>...etc) that's all the html that you need.
What you need next is Javascript.
In the button tag, you'll add an onclick handler like this:
<input type="button" value="Add Row" onclick="addRow()" />
Then you need the javascript. Something like this:
<script type="text/javascript">
function addRow()
{
var tbody = document.getElementById("tbody");
var newRow = document.createElement("tr");
var newCell1 = document.createElement("td");
var newCell2 = document.createElement("td");
newCell1.innerHTML = "Something more";
newCell2.innerHTML = "Something else more";
newRow.appendChild(newCell1);
newRow.appendChild(newCell2);
tbody.appendChild(newRow);
}
</script>
Every time you click the Add Row button, it will add a row to the table. Of course, you can extend this to include adding dynamic data or adding different elements to different parent elements (maybe adding a button when some condition is met... i dunno - I used it to add a row to a table - what you want to use it for is your own deal).
Here's the code from top to bottom:
<html>
<head>
</head>
<body>
<script type="text/javascript">
function addRow()
{
var tbody = document.getElementById("tbody");
var newRow = document.createElement("tr");
var newCell1 = document.createElement("td");
var newCell2 = document.createElement("td");
newCell1.innerHTML = "Something more";
newCell2.innerHTML = "Something else more";
newRow.appendChild(newCell1);
newRow.appendChild(newCell2);
tbody.appendChild(newRow);
}
</script>
<table>
<tbody id="tbody">
<tr>
<td> Something here </td>
<td> Something else here</td>
</tr>
</tbody>
</table>
<input type="button" value="Add Row" onclick="addRow()" />
</body>
</html>
A couple of things:
1) don't forget to add an ID to the element you want to add to.
2) don't forget the second 'a' in javascript. That one's a bugger.
Monday, April 16, 2007
Web Programming 1000
Well, I went to the University of Lethbridge and we had four-digit course numbers. So think of it as Web Programming 101 with a U of L flair.
The Eclipse IDE
In general, I like the Eclipse IDE. It's free, it's pretty rich as far as features:- Autocompletion
- API navigation
- quick switch to different classes/files
- the always-popular code-colouring/syntax-highlighting
- integration with lots and lots of different web servers
All but the last one I use quite often. I fought and I fought with the Tomcat integration plug-in. Sure, it installed just fine but I could not deploy an app to it to save my life. So, in my disappointment, I turned to ant.
Apache Ant is a program/framework which allows you to specify different targets (typically dist, deploy, test, clean) with tasks (including compilation, moving, copying, deleting, running certain programs). Gustavo, who I work with, helped me with learning Ant and I am excited with it. It means you don't have to be bound to an IDE for making your projects work (although compiling inside an IDE is a good way to work the bugs out) and your directory structure can be whatever you want it to be.
Directory Structure
I don't know standards, best-practices or conventions when it comes to directory structures. I know what tomcat wants when you deploy an application to it (since that's what I've been working on) so I have set up a directory structure that I'm comfortable with and I let my ant tasks put stuff where it needs to be.
Here's my directory structure:
Project folder
- Java
-com/org
-continue ad nauseum
The java and subfolders are where you'll find the java source code for the classes that I have written.
-Dependencies
-jars
-tlds
The dependency folder with its subfolders is where you will find the external classes/programs/libraries that I use in my project
-html
-jsp
-javascript
-html
The html folder is where you will find the front-end code - JSPs, HTMLs, javascript files, etc.
-web.xml
-struts.xml
-validation.xml
these files are stored directly under the main project directory. web.xml describes the application - entry points, etc. struts.xml does the same thing if the project is a struts 2.0 project. validation.xml describes the validation required on some web-pages. It's just an example of the xml files that will be under the main directory. Obviously there could be more.
I'm pretty much a beginner on this stuff, myself. I want to learn more about web.xml and struts.xml and figure out how to frame these files properly.
That and the specific ant tasks are what I'll write about next time.
Labels: Java, web programming 1000
Friday, March 30, 2007
Struts and messageResources.properties
I couldn't figure out how to get Javascript variables in there until Kevin, a sneaky-smart programmer who, like me has a background in C++, and who learned JSPs way faster than I did, pointed out a way to swap them in there after calling the bean:message.
In the messageResources.properties entry, stick an @2bReplaced in there where 2bReplaced is a meaningful variable name. So like this:
errors.badDate=The date @Date is bad.
Then in Javascript, you would do this:
var date = "02/25/-2007";//or something equally inane
var badDateMessage = "<bean:message key='errors.badDate' />"
badDateMessage = badDateMessage.replace(/@Date/g, date);
And then use the error message how you normally would.
So thanks, Kevin, for chucking that piece of functionality my way and making me and the UE people feel better about ourselves.
powered by performancing firefox
Labels: Struts
Wednesday, March 21, 2007
Happy Anno-versary
It's been a fast year. The amount of stuff going on, the amount of work yet to do and the lack of sleep have all combined to speed this year along.
It's hard to believe it's been a year but when I think about the way things were when I left Halliburton, maybe it's not so hard after all.
Here's to many more anno-versaries.
powered by performancing firefox
Labels: Off-topic
Friday, February 23, 2007
Javascript
I had to do some client-side validation for a form (after having spent a couple of weeks implementing the exact same validation, server-side). It took me two days because Javascript just works. You don't have to mess around with someone else's broken or crappy API. You just have to make it work.
[Ranterator: on]
The server-side validation I was doing was for an update function. It needs to be on the server-side. The exact-same validation goes on client-side for a pay function. Don't ask why we can't validate the server-side stuff client-side. It hurts to think about it. Anyway, we currently use Struts Commons validator for server-side. It doesn't work. If you have an indexed field (which we do) for validation, it will validate a certain field (amount, date, whatever) up until it runs into an error, then it will crash and die.
Okay, that was overly dramatic. It will complete the rest of the form, it just won't continue to validate that one field. So if you have five entries and it fails validation on, say email address for the second one, it will validate the rest of the form, but all of the other email addresses after the second one will not be validated. Sure, that may be okay for some people, but we want all failed validations to show up. Three lines of code. Three lousy lines of code separated us from this functionality. But I can't change struts code. So I jumped in and tried to wrap their code, inherit from their code, play nicely with their code but all of their stuff is sealed. Not sealed so much as every fucking thing I needed to use was private. So, I said screw it. I wrote my own validation method and used their validation results object (messily and with empty fields that just had names). It worked but I felt like my brain needed a shower afterward.
[Ranterator: off]
When I was coding the Javascript side, I discovered why they put those three lines of code in there. It's hard to properly label a failed validation when failing one causes it to fail a bunch. So I can understand why that would have been a thought. But there are a thousand different ways to deal with that, two of which I implemented. One in Java (server-side) and one in Javascript.
Instead of validating all indexes of a field at once, validate the whole indexed thing at once, chaining the validations so that if it fails the most severe one, it doesn't move on. (null before formatting before value-specific stuff) But Struts can't do that for some reason, and they can't have us able to derive from their code, so the stupidity continued. But I fought through it and checked in some ugly, ugly code that does what I want.
So yeah, Javascript's cool.
Labels: Javascript, rant, Struts, validation
Friday, February 16, 2007
Making the leap to Java 1.5
This was supposed to be a big feature that would save some typing, save some needless work and let things happen simply, the way the SUN intended.
Not so much.
There's no NULL handling behind the scenes, so with every autoboxing operation you do, you're just setting yourself up for an NPE. Forget it. Forget the three seconds of typing time you're saving and just leave the code the way it was. Obscure? Fine. Fuck it.
Don't use Objects, ever. Ever. Use primitives or you'll get some NPE you'll never chase down. The Classes have enough static members that use primitives that you'll never have to use an Object (hopefully) and then you won't have to worry about whether you're unintentionally autoboxing a stupid Object and setting yourself up for debugging hell.
Just use the primitives, man. And forget about autoboxing.
Until more later on,
Liam
This still exists?
So my first post this year in Intuitive Techniques will be this:
JAVA IS COMPLICATED.
All you people out there who say that Java is easier than C++ have no idea what you're talking about.
Sure there are a couple of things about C++'s memory management that are tricky, but Java has way more to it. Add to that the learning curve with all sorts of code-generation, frameworks, web programming and just about every kind of technology you can add and still call it a Java project and you have COMPLICATIONS.
Java-type and Java-based technologies on my current project:
Java (duh)
Ant tasks
JSP
Javascript
Apache Struts
JBOSS
Tomcat
Weblogic
Apache Struts-Bridge (it really is different from Apache Struts)
Liferay portal
Portlets
IntelliJ IDEA (which is the best IDE I've ever used)
QCommon - our own architectural framework
JUNIT
Put all of these together and you have a recipe for disaster. Somehow, though, the team I'm on has been able to keep up with a demanding schedule. I just wish I didn't feel like I was drowning most of the time.
I'll catch up. It's just a matter of when.
Yours in bugs,
Liam
(Next up: Java 1.5 -or- how to make something complicated easier to mess up.)
Labels: Java