BibleGateway.com Verse Of The Day
Wednesday, May 23, 2012
OSB Table Poller Issue Setting Status
Friday, December 03, 2010
WebLogic Annotation For MDB WorkManager
It ain't there. Not gonna do it. Not happening for you today, my friend.
You have to do a bastardized mutt application using a combo of annotations and XML deployment descriptors (remember those?).
Allow me to save you more time by showing a more concise example, so you don't have to take a time machine back to a time when EJB2.1 and XML roamed together in dinosaur-like bliss and figure out what the descriptor should look like.
Here's an example:
My MDB class signature looks something like this....
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "destinationType",
propertyValue = "javax.jms.Queue") },
mappedName = "jms.ens.yes943processing.queue")
public class YearEndProcessingMdb implements MessageListener {
...
And so on, with your onMessage() and all the other crap you would put in an MDB.
Then my weblogic-ejb-jar.xml file looks a bit like this....
<wls:weblogic-enterprise-bean>
<wls:ejb-name>YearEndProcessingMdb</wls:ejb-name>
<wls:dispatch-policy>Ens943WorkMgr</wls:dispatch-policy>
</wls:weblogic-enterprise-bean>
<wls:work-manager>
<wls:name>Ens943WorkMgr</wls:name>
<wls:max-threads-constraint>
<wls:name>Ens943MaxThreadLimiter</wls:name>
<wls:count>10</wls:count>
</wls:max-threads-constraint>
<wls:ignore-stuck-threads>true</wls:ignore-stuck-threads>
</wls:work-manager>
</wls:weblogic-ejb-jar>
You can tell if the thread limiter is working by deploying, chucking a bunch of messages on thequeue, and checking the WLS console.
- Go to deployments
- Click to expand your EAR
- Click on the MDB name.
- Then go to the Monitoring tab.
- Under that click on the Workload tab.
- Here you should see your work manager and thread constraints with the number of messages they are processing.
Monday, November 01, 2010
Oracle Service Bus - Getting XML Out of Table Column
Let's say you have a table you need to query from the OSB. The result set you get back from the JCA DB adapters gets turned into XML for you. If one of the columns is a LOB containing XML, then it gets escaped using CDATA. Anything in CDATA is basically ignored by XML, XSL, XPath, etc.
It is a 2 step process to extract that value and make it usable XML:
- Use the fn:string() function to turn the value into a string. In this case, it strips off the CDATA wrapper and gives you a string that looks like XML.
- Use the fn-bea:inlinedXML() function to parse that string into XML.
You can use an ASSIGNMENT task to jam that XML into a variable, and then run any XSL, XPath, etc on it. You can also use INSERT or REPLACE tasks to embed it back into your original XML.
Wednesday, October 13, 2010
A Few More SEAM Nuggets
Showing Number of Matched Records in List View
When you generate a SEAM application from a database, you end up with a set of components for each table - for example a list view, record view, and record edit. When you are displaying a list of records, it is common to want to show how many records match the current query (or the total records if you went to list view without a search criteria).
You can easily get this function by accessing the "resultCount" attribute on your view, like this:
<h:outputtext value="#{yourTableList.resultCount} rows found." rendered="#{not empty yourTableList.searchResults}">
Change Default Sort Order, But Still Allow Click-To-Sort
One requirement we ran into on one of my SEAM projects was to change the default sort order for some of the list views. However, the views that the SEAM gen tool creates allows the user to click on the column headers to change sorting as well. To achieve a default sort order on initial load, and still allow clickable headers, override the getOrder() method in your
@Override
public String getOrder() {
String order = super.getOrder();
if ("".equals(order) || order == null)
{
order = "col1 asc,col2 desc";//your default sort columns here
}
return order;
}
Wednesday, October 21, 2009
Running Multiple Versions of Oracle JDBC Driver on same JBoss server
With the newer JDBC driver out in the Jboss server's lib/ directory, the legacy application fails to connect because of the dreaded ORA-604 that you get when trying to connect to a really early DB with a driver that doesn't go back that far. See the links below for Oracle's list of what drivers support what versions of Oracle. The exception is shown below in case you haven't seen it before.
Throwable while attempting to get a new connection: null
org.jboss.resource.JBossResourceException: Could not create connection; - nested throwable: (java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1
ORA-02248: invalid option for ALTER SESSION
Putting the old driver out in lib/ means that the newer datasources won't deploy properly.
After a few hours of Google searches and pouring through the Jboss.org wiki and forums, we just couldn't find the answer. We finally made this post to the Jboss forums:
We are using Jboss AS 4.2.2-GA and have hit a snag. One application needs to connect to an older Oracle 8 database, so we need to use the older Oracle JDBC driver. For all of our other applications, we need to use the newer Oracle JDBC driver.We got the response the next morning, and it turns out we were on the right path by putting the datasource file and classes12.zip in the application EAR file, but because of JDBC classloader issues, we had to also include a few other files and some extra application.xml config. Here is the complete article.
But the classnames for the drivers are the same, so we can't figure a way to tell one *-ds.xml file to deploy under the early driver and everything else to use the newer driver.
We tried adding the older driver JAR file and the *-ds.xml file right in our application EAR file, but when deploying it picked up the newer Oracle driver from the server's lib directory anyways. This puzzled me as we are using ear-scoped classloaders.
Both applications are SEAM applications using EJB3/Hibernate. We can get one or the other to work depending on which Oracle driver we put in lib/ but can't get both to work at once.
I've been searching Google and the Jboss forums and wiki for the past 2 hours, and find lots of newbie "this is how to deploy a datasource" stuff, but nothing on 2 conflicting versions of a vendor's driver. HELP!
Links:
- My post to Jboss forums asking the question: http://www.jboss.org/index.html?module=bb&op=viewtopic&t=162701
- The wiki article that answers the question http://www.jboss.org/community/wiki/IWantToDeployMyOwnJdbcDriverInAScopedClassloader
- Which Oracle JDBC Drivers support which versions of Oracle RDBMS? http://www.oracle.com/technology/tech/java/sqlj_jdbc/htdocs/jdbc_faq.html#02_02
- Jaikiran Pai's blog - gotta give props to the guy who answered our question: http://jaitechwriteups.blogspot.com/
Tuesday, August 18, 2009
Multiple Column Subqueries (Oracle)
For my own benefit, I am posting the basic syntax for next time I need to do it. Replace your table names where t1 and t2 are, column names for c1, c2, c3, etc. I did this in Oracle, but it may work the same or very similar in other databases.
SELECT *
FROM t1
WHERE (c1,c2,c3)
IN (
SELECT t2.c1,t2.c2,t2.c3
FROM t2
)
For reference, I found my answer at: http://www.java2s.com/Code/Oracle/Subquery/WritingMultipleColumnSubquerieswithtablejoin.htm
Wednesday, July 15, 2009
More Jboss SEAM Nuggets
-Doracle.jdbc.V8Compatible=true
-Djava.awt.headless=true
<web:context-filter pattern="/csv"/>
UnmappedAccount unMapAcct = (UnmappedAccount)Component.getInstance("unmappedAcct");
import org.jboss.seam.annotations.Name;...@Name("unmappedAcct")public class UnmappedAccount { ... }
Allow me to throw out a minor warning on the generated SEAM code. The default CascadeType in the generated EJB's is "ALL", as seen in the annotation below.
It's not devastating, it's not a bug, but it is something you should be aware of in case you don't want cascading (or worse, aren't aware of cascading and what it really means, and just happily go with the defaults).@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "...")
See http://java.sun.com/javaee/5/docs/api/javax/persistence/CascadeType.html for more information on the various CascadeTypes, in case you don't already know. If you don't want cascading, remove the "cascade = CascadeType.ALL" portion of the generated annotation.
Let's say you try to delete a record that has children records attached to it. You might expect to get an error back saying you can't delete a record that has children attached. That's what you would get from, say TOAD or Squirrel or SQL-Plus, or even from applications written using plain old ODBC or JDBC statements. But with cascading, that delete will happily take care of those children for you without complaining ;-)
Wednesday, April 08, 2009
Google App Engine And Java
For now, the only supported language is Python....I wouldn't mind seeing other languages supported in GAE, though not sure it really matters or if it is worth Google's time, money, and effort to expand support to other languages. I'm sure if they asked 100 developers they would get 100 different answers of what languages should be supported.Well, just when I was getting used to the idiosyncrasies of the Python language, I went to look something up on http://code.google.com/appengine/ and found that they have an early preview of Java running on the engine. Here's the blog posting.
If I were one of the 100 developers mentioned above, my first answer would have been Java. I signed up as soon as I saw it, but alas, I'm on a waiting list. Looks like I'll be flirting with Python a little longer while I wait for my true love....
The really cool part of getting Java running in the engine is that should bring the other languages that run on the JVM as well, e.g. Scala, Groovy, JRuby, BeanShell, and, yes, even Jython.
Oh the fun!
Tuesday, March 31, 2009
Google App Engine & Python
I was surprised at how well done the Google App Engine is, and how quickly I could get started. Downloading and installing the local development environment was quick and painless, and walking through the tutorial, I had a very basic "guest book" application written and deployed out in the vast Google cloud for the world to see. The local development server was up and running within minutes of downloading and installing, and making changes to the Python scripts didn't require any redeployment or restarts. Uploading to the Google servers was a matter of running a single script and entering your user id and password. There is even an admin console where you can see stats on your page visits, bandwidth used, performance, etc.
I like that the Google users and authentication is pretty much built in, as well as the simple "webapp" MVC framework, and that you can use any pure Python library or framework you want to use (as long as there aren't any extensions written in C). The data access layer and GQL query language is interesting -- one big free-form data store where you aren't dealing with individual tables so much as just defining your entities in your code's data structures, and reading and writing from them as if they are tables.
For now, the only supported language is Python, which I have never dealt with. That really wasn't much of a hurdle since the syntax is pretty straight forward and easy to learn. I wouldn't mind seeing other languages supported in GAE, though not sure it really matters or if it is worth Google's time, money, and effort to expand support to other languages. I'm sure if they asked 100 developers they would get 100 different answers of what languages should be supported.
I'm a little more ambivalent toward Python. I didn't dislike it, but it just didn't grab me by the balls and make me exclaim it's superiority either. I can say I'm not a fan of the whole "indentation exception" crap. As a guy with more of a C and Java background, I like my curly brackets instead of relying on indentation levels, which remind me too much of COBOL, yuck!
Anyway, here's my trivial little application. It's all "tutorial-ware", straight out of the book with a few CSS enhancements and a simple "about" page. It's not useful, but not bad considering how little time it took to write.
Next step.... write something useful. I definitely want to get into this more and add it to my development toolbox.
Tuesday, March 03, 2009
An Overzealous SEAM Validation
When you use Jboss Developer Studio (JBDS) to reverse engineer your database (I imagine the seam-gen tools do the same since JBDS uses them), the getter method on the EJB looks something like this...
Looks fine, looks reasonable. Single character fields are often used for flags or indicators, as this one above is -- it's a simple Y/N field. So in my XHTML I use a radio button control instead of a free form text field.
@Column(name = "DEFAULT_REMAP_IND", length = 1)
@Length(max = 1)
public Character getDefaultRemapInd() {
return this.defaultRemapInd;
}
<h:selectOneRadio id="defaultRemapInd" value="#{ocamCustTypeDfltHome.instance.defaultRemapInd}" required="true">
<f:selectItem itemValue="Y" itemLabel="Yes" />
<f:selectItem itemValue="N" itemLabel="No" />
<a:support event="onblur" reRender="defaultRemapIndDecoration"/>
</h:selectOneRadio>
Not sure how to get a single character with a length greater than 0 but less than 1, but I do know that the easiest thing to do in this case is remove the @Length annotation for that field. I had to do that for a few different tables. Luckily they were all flags that could be replaced with radio buttons, but in the case where you had to allow free input, you might have to get more creative (you can always put a max length on the input text field).
For reference, I am using Jboss 4.2.2, SEAM 1.2GA, Jboss's EJB3 implementation (which is Hibernate under the hood), XHTML and Facelets for the views. Like I said, this might be fixed in a later release of SEAM.
Monday, August 18, 2008
Simple JSP To List Java JVM Environment
I'm sure every Java developer has written similar code at some point, so I won't claim it's original, unique, or ingenious. But if you find it useful, go ahead and use it instead of writing another.
Sunday, May 18, 2008
Jboss SQL Deployer
It consists of a class implementing java.lang.Runnable (a Thread) that wakes up every 20 seconds or so and scans a directory for any new SQL files. Of course there is also a class implementing java.io.FileFilter to look for just SQL scripts. To turn this into a JMX service, I wrote a simple BeanShell wrapper to drop into the deploy directory.
Once a SQL file is found, the code assumes the first line will contain the DataSource JNDI name, so it knows what database to connect to. Then it currently assumes the rest of the file is one query. The query results are formatted and dumped to STDOUT.
To make this truly useful, I will have to make it accept updates as well as queries, and parse the file looking for multiple SQL statements instead of assuming it is just one. Other than those limitations, it works great with the few tests I have done so far. I have been testing under Jboss 4.0.3, but this should work with any version of Jboss with the BSHDeployer.
SqlFileScanner.java
SqlFileFilter.java
sqldeployer.bsh
Why would you use this? That's always a good question to ask, and this time I have an answer besides "because you can".
- Running ad hoc queries right from your app server, using the same Jboss DataSource bindings your applications are using, and from the same server your apps are running, can be very helpful in troubleshooting issues.
- Let's say you use Realms instead of username/password in the DataSource XML descriptor, for security reasons. Now you can troubleshoot database issues as that user even without knowing the DB username and password.
- Set up simple reporting jobs without needing an Oracle client installed on the machine -- run them right from Jboss.
I think I may create a new open source project to house this as well as all the other Java "odds and ends" I have written over the years, like some of the code generators, MQ tools, servlet filters, JSP tags, etc. The hardest part will probably be coming up with a meaningful project name -- who wants to download and install "RobbsRandomJavaCrap.jar"?
Thursday, May 01, 2008
Some Old-School JAM and JPL Tips
I was cleaning out the barn and found a CD of some old code and documents I had written at an old job, kind of a "portfolio" CD if you will. We used JAM to build Motif screens.
JAM let you visually build your screens, and had it's own procedural programming language, JPL (JAM Programming Language). JAM came with the necessary C code to handle launching of the screens and handling events. You could write your own custom C code to be called from the screens, or write your code in the JPL file for the screen, or a combination of both. One nice thing is you could write SQL code right inline with the rest of your JPL (just prepend the keyword "sql") and everything was taken care of, even down to binding the result set to variables.
It's not exactly cutting edge technology now, but I know it is still in use by at least a few companies. This is not a tutorial for non-JAMsters, but rather a collection of troubleshooting tips I had taken note of. Maybe this could be of use to someone just inheriting legacy apps, or who knows when I might run into JAM again. Yuck!
For reference, these tips are mostly for JAM 5 and 7, but they may be applicable for other versions as well.
| SELECT 1 FROM table... | This is often done to see if a record meeting your criteria (where clause) exists in the table. Doing this from a JAM screen (at least in Jam 5) will produce a @dmrowcount of 0 (zero), even if there are records in the table meeting the criteria. There are two alternatives within JAM to get the same information: 1. SELECT COUNT(*) temp_var FROM table... 2. SELECT column temp_var FROM table... |
| SELECT column FROM table | This one can be tricky. If there is no JAM variable with the same name as the the selected columns, then JAM will create those variables and put the results of the query in those variables. If the variables do exist already, JAM will overwrite the values with the results of the query, even when the query returns nothing (it will essentially clear the variables). |
| Mixed Case Variables | Mixed case variables can be a real problem with JAM, and the error messages are not intuitive enough to let you know what the real problem is. Keep tihs in mind when you can’t figure out some quirky behaviour, and all the other logic and syntax is proper. |
| Changes in screen file don’t seem to take effect | Check the local directory you are running from. JAM will use screen, JPL, and dictionary files fro mthe current directory before checking in the SMPATH, regardless of what the SMPATH is set to. Check the data dictionary. The screen fields and variables can be stored in here, as well as in the screen definition file. Data dictionary tends to overwrite local (screen) vars. |
| Some Useful environment Vars | Most of the relevant environment variables start with SM, e.g. SMVARS, SMPATH |
- Also worth noting is that while it might make sense that they would just make use of the underlying Motif widgets, in some cases that was not the case. Simple text boxes for instance would not work with bi-directional Hebrew whereas pure Motif screens did. We had to have JYACC / Prolifics issue a patch for us before we could release to an Israeli customer.
- There were also issues with some characters in the Turkish (ISO-8859-9) character set. Their database layer simply could handle it for some reason. Wouldn't bring back results, wouldn't update, and yet We ended up having to write our own generic database access layer using Pro-C, and replacing all the JPL "sql" statements with "call" statements into our library.
Tuesday, April 29, 2008
Some Notes On The Jboss BeanShell Deployer
public interface ScriptService
extends org.jboss.system.Service
{
public String objectName ();
public String[] dependsOn ();
public Class[] getInterfaces ();
public void setCtx (ServiceMBeanSupport wrapper);
}
It was extremely easy to write a few scripts and drop them in the deploy directory. Of course, you can start with the requisite "Hello World" script, which upon deployment, prints out to the console. A few more minutes of scripting (adding the above methods) yields a service mbean that can be managed via JMX.
But then the obvious questions: Why? Why would I write mbeans using bsh instead of Java? What do I gain? What do I lose? Is it really any quicker?
I don't really have good answers for the why question yet. I did write a few services using bsh. They were easy enough to implement, but nothing that couldn't have been done in a similar time frame using Java. You lose compile time error checking, but you avoid some of the plumbing regarding build scripts, deployment descriptors, and building .ear or .sar files.
I did write a few services. One connected to a Websphere MQ (a.k.a. MQ Series) queue manager to get queue depths and print them to the Jboss console. I ripped most of the code right from an existing MQ tool I wrote a few years ago. So not the most useful thing in the world, but it proves out importing existing Java classes and the Java syntax. Another used JDBC to connect to an audit database and purge old transactions. Again, nothing that couldn't be done in regular old Java code in the same amount of time.
Overall, I didn't feel like I was saving any time. For one, the syntax is Java. That's great for code re-use (either cutting/pasting or importing libraries), but Java syntax doesn't have that "lightweight scripting" feel to it. Also, the lack of compile-time error checking doesn't save you much time if you have to run the script to find errors. Make a simple mistake like a type mismatch or failing to catch a specific exception, and your IDE and/or compiler will tell you about it. Do the same thing in a bsh script, and you find out after you deploy it and run it.
I think this could prove useful in the future, as one more tool in my programming toolbox, but have to admit I don't have a lot of use for it right now. Maybe I'm just not seeing the big picture, or just haven't run across the scenario where this is the ideal way to solve a problem. If you are using the bsh deployer, please let me know what you are doing with, or what types of problems you are solving with it.
Once I have a reason to use it, at least I know it is easy to do. And once the why question starts to have answers, maybe I'll explore writing a JRuby or Groovy deployer. Or actually, what would be really useful would be a SQL script deployer, so you could run ad-hoc queries against your Jboss DataSources without writing JDBC code or having to launch a DB tool like Squirrel or TOAD. Since Jboss deployers are service mbeans, maybe I could write the SQL deployer in bsh...
Monday, April 14, 2008
The BeanShell Servlet Filter Summary
So to summarize:
- What's the point? It's a Java Servlet Filter that delegates to BeanShell scripts to do the actual Filter work.
- Does it really work? Yes. I am currently running it in Glassfish, but should work in any Java servlet container. It's still just a proof-of -concept and needs to be cleaned up to make it production ready.
- Where's the code? Of course, you still have to go to that post to see the code, but you can skip the blathering on and on and on.
- What's the point? Well, just because it can be done I guess. My theoretical ramblings on "why" are what made the post so long in the first place.
Saturday, April 12, 2008
Dynamic Servlet Filters Using JVM Scripting
But what if you could not only enable or disable the Filter, but also change it's behavior, on the fly at runtime without special build or deploy steps. I was pondering this idea and came up with the concept of a Servlet Filter, that by itself, does nothing.
Nothing? Well, nothing by itself.
"By itself" is the key phrase here. Instead of doing something in the Java code (getting timings, checking security, auditing calls, printing debug statements, etc.) it just instantiates a scripting engine, like BeanShell (BSH), JRuby, Groovy, etc. It starts up the scripting engine, passes the Request and/or Response objects, and runs a script that you have identified. That script does all the meat-n-potatoes work, and the Filter then calls next in chain like it normally would. And the best part is, the script could be changed at runtime, from a simple do-nothing-and-return to full blown screwing around with the Request and Response objects.
I've developed a proof-of-concept (POC) and have it running under Glassfish v2 application server. I used BeanShell for the scripting engine in the POC, but as stated above, any of the scripting engines for the JVM should work. This isn't quite ready for primetime, but it fully works.
There are actually 2 scripts called by this filter, one before the chain.doFilter() call is made, and one after. That way you have the flexibility to do operations either on the request, on the response, or both.
First, the Java code for the Filter:
Then, the 2 BSH scripts:
BSHServletFilter_PRE.bsh
import java.servlet.*;
import java.servlet.http.*;
import java.util.*;
System.out.println("This is the BSHServletFilter_PRE.bsh script!!!");
StringBuffer output = new StringBuffer();
output.append("\nRequest Attributes\n");
Enumeration attrs = request.getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = (String) attrs.nextElement();
output.append(attr +" - " + request.getAttribute(attr));
output.append("\n");
}
output.append("Request Parameters\n");
Enumeration params = request.getParameterNames();
while (params.hasMoreElements()) {
String param = (String) params.nextElement();
output.append(param +" - " + request.getParameter(param));
output.append("\n");
}
System.out.println(output.toString());
System.out.println("This consludes the BSHServletFilter_PRE.bsh script!!!");
BSHServletFilter_POST.bsh
System.out.println("This is the BSHServletFilter_POST.bsh script!!!");
System.out.println("About to alter the response...");
response.getWriter().print("<h1>This response is from the BSH script</h1>");
response.getWriter().flush();
System.out.println("Done altering the response");
And the browser screenshot...
This is currently just at the POC stage. It is working as-is, running under Glassfish. But as you will immediately notice, the filenames for the scripts are hard-coded, and there is definitely some more cleanup to make this production quality code. But, you can change the behaviors of the filter, for better or worse, at runtime without any compiling, deploying, or restarting of servers. You can even "disable" the filter by writing BSH scripts that do nothing.
Thursday, April 10, 2008
A Servlet Filter For Easier Debugging
This isn't meant to be a tutorial on Servlet filters, I am assuming you either know (or know how to figure out) what filters are, and how to tie them into your application in the web.xml descriptor.
I "printed" the source into a PDF to keep the formatting in tact. Here is the link, or if your PDF plugin is working, it should appear in an iframe below....
Monday, March 17, 2008
Oracle on Windows Authentication Woes (And Solutions)
Except that several times already, when trying to run imports or simply connecting via SQL-Plus, I get the following crap:
C:\oraclexe\app\oracle\product\10.2.0\server\BIN>sqlplus XXXXXX/XXXXXThe first time it happened, I simply restarted the OracelServiceXE and OracleXETNSListener services. Then it happened again today, and restarting services had no effect. And I am NOT rebooting my whole machine just to get Oracle to work.
SQL*Plus: Release 10.2.0.1.0 - Production on Mon Mar 17 08:50:29 2008
Copyright (c) 1982, 2005, Oracle. All rights reserved.
ERROR:
ORA-12638: Credential retrieval failed
But thanks to someone named "babu george" on this forum, I fixed the issue quite simply by getting rid of NTS authentication.
In your sqlnet.ora file, simply comment out the (NTS) line and create a new line with (NONE) in place of (NTS).
#SQLNET.AUTHENTICATION_SERVICES = (NTS)Alas, don't get me started on how much I love Windows.
SQLNET.AUTHENTICATION_SERVICES = (NONE)
Friday, March 14, 2008
Trashy Yet Effective Oracle Trick
I need to post this so I can remember it next time I screw up...
I was running an Oracle import (imp) on my local Oracle 10g XE instance today, and realized I did it incorrectly and imported everything into the SYSTEM schema. Oh crap, I can't just wipe everything out, it's my SYSTEM schema! I need surgical precision to only remove the crap and leave all the Oracle stuff unscathed.
Then, like a tornado in a trailerpark, it hit me. An idea that walks the fine line between genius and insanity. All the new table names started with a common prefix, which for sake of discussion I will call "BLAH_". So in Squirrel I run the following query:
select 'drop table system.' || table_name || ';' from all_tables where owner = 'SYSTEM' and table_name like 'BLAH_%'
Then cut and paste the results back into the Squirrel query runner and run the results as a script.
I'm sure there's an "official" way to accomplish the same thing, but screw that, this was extremely quick and kind of fun.
Trashy yet effective.
Monday, February 25, 2008
FCKeditor - Embedded HTML Editor
After hitting Google, I ran across FCKeditor. I had heard of it before, and even played with the demo once, but never did anything with it. Never had much of a reason to. Today that all changed.
After reading through the Developers Guide, I downloaded the ZIP, unpacked into my public web directory, and had it working in no time. In less than 30 minutes, I had the FCKeditor completely tied into an existing Rails form, replacing a boring old text area. After a few minutes of testing inserts and updates, and some cross-browser testing with Firefox and Internet Exploiter, I was happy.
There were only a few lines of JavaScript code to add to the page, and those are all spelled out in the Developer's Guide, so I don't feel the need to repeat those here.
Overall, I was pleasantly surprised. Unlike a lot of open source projects out there, this was extremely easy to get started with, easy to install and embed into existing applications, and the documentation was pretty good for a change. The quality so far has also been nothing short of impressive. (the editor is more full-featured than the one Blogger uses.)
It's licensed under the GPL, LGPL, or MPL (your choice), and can be embedded in any project, open source or commercial. Also, in addition to the JavaScript version I used today, there are versions for JSP, ColdFusion, PHP, Python, etc.
This project today was just a personal side project, but I think FCKeditor might find it's way into my arsenal for work projects as well.