blogs
|
|
jason
|
|
Written by jason
|
|
Monday, 01 March 2010 00:00 |
|
Every software project has dependencies: your own resources, your own APIs you've created, third party APIs and projects, etc. We've all had to deal with them at some point in our career. Recently while playing with Gradle (www.gradle.org) I've come to a realization about how they should be handled correctly. In this post, I'll talk about the two most prominent kinds of dependencies, their scopes, and where they fit into an application. I will not be discussing packaging or how the different scopes must be resolved to create a distributable / deployable artifact. Being a Java developer this is seen from within the Java space, but the concepts are universal to all software projects.
Dependency Types
There are basically two types or categories of dependencies: first level and transitive. First level dependencies are those resources that your application directly relies upon. Examples of first level dependencies include the language in which the project is written, entities your project directly uses such as an XML parser, images, and classes from a third party project. Transitive dependencies are dependencies of your first level dependencies. An example from the Java world could be commons-logging which is dependent on some logging implementation, commonly log4j or JDK logging. For commons logging the log implementation is a first level dependency, but for your project it's a transitive dependency. Another example may be an SAX XML parser (or any other XML parsing API). The SAX API is used directly by your project and is therefore a first level dependency, but it requires an implementation, possibly Xerces, which would be a transitive dependency of your project. This definition of dependencies has really been ingrained in me while using and trying Gradle (a build system [yes, another one] written in Groovy). In the past I've used Maven or Ivy (basically as a Maven alternative, but it does much more in the world of dependencies). Maven introduced me to the concept of transitive dependencies and how they fit into it's life cycle and therefore your project's life cycle. I owe a great deal to Maven for introducing me to the concepts, but Maven has a few blemishes (at least I think so) in the way it handles these different types of dependencies. Maven will by default (I don't think you can change this) include all of the transitive dependencies of the same scope in your classpath, which in my opinion, is incorrect. Here's an example taken from JSFUnit: pom.xml:
<dependency>
<groupId>net.sourceforge.cssparser</groupId>
<artifactId>cssparser</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<scope>compile</scope>
</dependency>
Dependency Tree:
[INFO] +- net.sourceforge.cssparser:cssparser:jar:0.9.5:compile
[INFO] | \- org.w3c.css:sac:jar:1.3:compile
[INFO] +- net.sourceforge.nekohtml:nekohtml:jar:1.9.9:compile
[INFO] | \- xerces:xercesImpl:jar:2.8.1:compile
[INFO] +- xalan:xalan:jar:2.7.0:compile
[INFO] | \- xml-apis:xml-apis:jar:1.0.b2:compile
For this project cssparser, nekohtml and xalan have been configured as first level dependencies, but the effective classpath contains their compile (first level) dependencies as well. If the project relies on these libraries it should state them explicitly and not rely on the crutch of having them as transitive dependencies. Ivy usage can fall into the same problem, but this is not the case in Gradle (at least not without changing the default), which I believe is the correct way of handling first level dependencies. With Gradle the compile scoped (more in the next section) is not resolved transitively, so you'll have compile time errors if you have not declared a needed dependency.
Life cycle Scopes and Dependencies
The build life cycle for a software project can be distilled into three phases: compile (if needed), test, and runtime. Test is a little special because it contains two phases itself: testCompile and testRuntime, which are extensions of compile and runtime. So where do the different types of dependencies come into play? Your first level dependencies become your compile dependencies and runtime dependencies are pretty much your compile dependencies with transitive dependencies and a few other things that may be provided for you like container provided dependencies (though, those are arguably transitive dependencies of any third party dependency) such as a messaging provider, an HTTP implementation, transaction support, etc. The test dependencies extend compile and possibly runtime, and add their own dependencies for testing: a testing framework, mocking framework, possibly a slimed down server, and others, which of course would be first level dependencies for your tests.
Summary
To recap, there are two different kinds of dependencies: first level and transitive. First level are dependencies needed to build an run your project. Transitive dependencies are those dependencies of your dependencies. A software build life cycle essentially has three phases: compile, test, run. The compile phase should only use your first level dependencies. Runtime extends compile and is resolved transitively. Test extends both compile and runtime (though at different times) and uses its own dependencies as well. I hope this has been informative and helped others understand the relationship and distinction of dependencies and a software project.
|
|
|
jason
|
|
Written by jason
|
|
Monday, 01 March 2010 00:00 |
|
I would like to thank those who provided feedback for Part 1 of this exception handling series. A special thanks goes out to Dan Allen and Dan Hinojosa for the wonderful constructive feedback. I'm sure over time these posts will improve and become better.
This entry was originally going to be talking about custom handlers and provide some code; however, due to family and work factors I have not been able to finish what I wanted for this. Instead we'll be diving even further into the built-in handlers and providing examples. At the end I'll also give a sneak peek of the exception handling framework that will make up Part III of this series, hopefully complete in March. To cut down on the length of this post I've linked to Seam's Fisheye install of the 2.2.0.GA release. With that, let the journey into org.jboss.seam.exception begin!
This class (org.jboss.seam.exception.Exceptions) is a built in Seam class, all you need to do is obtain a reference to it (either via injection @In("exceptions") Exceptions or Exceptions.getInstance()) and call thegetHandlers() method to add your own exception handlers. Typical interaction is done by adding exception handlers via the annotations or pages.xml. Let's begin the exploration with the initialize() method where all the initial setup and creation of the built-in handlers happen. Handlers are added in the following order:
- AnnotationRedirectHandler
- AnnotationErrorHandler
- Handlers declared in pages.xml
- User defined custom handlers (more on this later)
At first glance, it appears that an old deprecated way of adding exceptions is first added, then the exception handlers added via page(s).xml; however, this is not the case as each of those ExceptionHandlers is added to a list, then added at the end. Just before any handlers that the user specifies with pages.xml or custom handlers the Seam Debug Page is added.
It's important to know that while in debug (typically only development mode) your annotated exceptions will take precedence over the Seam Debug Page, and nothing after the debug page will be triggered (the debug page is a global catch all handler).
The parsing of the XML files happens in the parse() method which does some basic XML parsing looking for the exception elements. The class and logging level (if configured) are pulled from the exception element, and a new ConfigRedirectHandler or ConfigErrorHandler is created (more on these handlers later). If there is no class attribute specified then a catch-all handler, that handles Exception.class is created.
The private createHandler() method does the work of pulling additional information about the configured handler such as
- ending conversations
- redirecting
- adding FacesMessages
- finding the http error code, etc.
The correct handler is then created and returned to be added into the list.
The only other part of this class that has any importance for the developer/user is the handle() method, which is really just an iterator over the handlers looking for a handler for the exception which was thrown. Though there is a catch: Nested exceptions are unwrapped and handled from the bottom up (though in the Seam Debug Page the exception is recreated so you may need to scroll to the bottom to actually find the real exception). If a long running conversation is active then the "org.jboss.seam.handledException" object, which is the exception object, is added to the conversation context. If logging is configured for the exception handler a log message is added then two events are raised (regardless of logging): "org.jboss.seam.exceptionHandled." + cause.getClass().getName() and org.jboss.seam.exceptionHandled allowing a further user extension point if so desired. If no handler is found then an event is raised ("org.jboss.seam.exceptionNotHandled") and the exception is rethrown. Even if this event is observed, (the exception is passed as a parameter to the observer's method) it will not be able to influence the exception being rethrown.
Any handlers the developer creates and adds to the Exceptions list will be added at the end of the list (unless the list is manually modified and rearranged, which is allowed). Depending on the specific needs of the application this is a great place to add a general catch all handler for the application (unless a general handler in pages.xml is sufficient). When adding custom handlers or any handler really, it is important not to create multiple handlers for the same exception as the first in the list will be called and the list of handlers will terminate with that handler.
ErrorHandlers (AnnotationErrorHandler and ConfigErrorHandler) are a specific type of ExceptionHandler, they're used to send an HTTP Error code to the browser, probably more useful when combined with Seam's Web Service or REST integration. There is not a lot of code to these handlers, in fact, they are only data containers used by the parent class ErrorHandler which handles sending the error to the browser. However, they are great examples of reuse for exception handling, and make for good templates to follow in abstracting logic in custom handlers. The two sub classes hold
- the message (if configured)
- the error code number
- and the flag to end the currently conversation.
All of the logic to make it happen is in the handle() method.
The redirect handlers (AnnotationRedirectHandler and ConfigRedirectHandler) are in the same category as the error handlers: there's not much to them, and most of the interesting code is in the parent classRedirectHandler. The first bit of code in the handle() method is finding the viewId if none was specified in the handler instance, but it really isn't related to the actual exception handling. Next is the addition of a defined FacesMessage, ending the conversation (again, if configured), and finally the redirect.
This is a great handler (source) along with the associated code in the jboss-seam-debug.jar to fully understand the potential of exception handlers in Seam. The handler is really the entry point into the debug system in Seam. Java code wise, there's not much to it, it's a redirect handler that sets some additional parameters for the redirect. The whole process of Seam Debug really could be it's own blog entry or series of entries. It's pretty involved: it includes a PhaseListener, a SerializationProvider, and some custom Introspection. Because it's such a large, involved piece of code, I'll cover it more fully in a future post, or perhaps a whole series.
Examples
Annotations
Consistent with the rest of the framework, Seam provides a few Annotations to help with exception handling, these were briefly explored in Part I. Here are some examples on how they're applied to application code.
@ApplicationException(rollback=true)
@Redirect(message="This item is out of stock")
public class OutOfStockException extends Exception {
...
}
The @ApplicationException annotation is a mirror of javax.ejb.ApplicationException with additional support for ending a conversation. It is also the entry point Seam uses to configure annotation based exception handlers and must be used if the @HttpError or @Redirect annotations are to be used. In this particular example some of the defaults are used such as not ending the conversation (with the end attribute) and there is no redirect happening, but the message (which can also take an EL expression for i18n, or substitution purposes) will be displayed on the page where the exception occurred.
This next example might be useful with Seam's WebService support, it will return an HTTP error code 500(probably not the most useful for the clients, but it's an example, right?).
@ApplicationException(rollback=true)
@HttpError(code=501)
public class OutOfStockWsException extends Exception {
...
}
As noted earlier, these two exception handlers (AnnotationRedirectHandler and AnnotationErrorHandler) are the first two handlers in the list and will be the first called to handle the exception, if they are capable, as defined by boolean isHandler(Exception). The classes use the meta data from the annotations to determine if the exception can be handled by one of these two classes. Next up is a closer look at defining the same exception handlers in pages.xml.
Exception handlers can only be defined in the pages.xml, not in the individual page.xml files, which in my opinion is a bit of a short coming. There could be times when the same exception should be handled differently for different pages.
Pages.xml
Because the handlers for pages.xml are roughly the same handlers, different sub classes but they do the same as the annotation sub classes, the above handlers could be declared via pages.xml with the following XML:
<exception class="OutOfStockException">
<redirect>
<message>This item is out of stock
</redirect>
</exception>
<exception class="OutofStockWsException">
<http-error code="501" />
</exception>
Pretty simple stuff. These exceptions will follow the annotations in the list (it's worth noting that each exception that is declared in the XML creates a new instance of the associated handler, unlike the annotation counterpart). If both were declared in the same application the annotation ones would be used. Both ways get the job done, and for your own exceptions it's really just a matter of preference.
The pages.xml declaration really lends itself better for exceptions that cannot be annotated, such as form Hibernate or JPA, please see Part I for examples.
Part III of this series will demonstrate an exception handler framework that could be plugged into Seam and will allow chaining for handling (for example send an email or IRC message and create a bug report for the exception). It should be generic enough to work with Seam, JSF2 (Ed Burns talked about JSF2 Exception handling on his blog), or even the base JRE (yep, 1.5 added Exception handling). It will be hosted on GitHub.
|
|
jason
|
|
Written by jason
|
|
Friday, 01 January 2010 00:00 |
|
This three part entry will focus on the mechanisms Seam provides for handling exceptions gracefully -- both out of the box and extensible. An in depth look at where this happens in the Seam code base and user programmable extension points will be covered in Part I. Part II will dive even further and provide examples, and Part III will cover a custom ExceptionHandler implementation. Exception handling in any large application is something that's typically debated at least once: What does it mean, is it simply logging, what do we show the user, can our framework help etc. etc. All software developers will run into this debate at least once in their career, even if it's as simple as "what should I put in that catch block?" It's pretty safe to say swallowing exceptions (as a general rule of thumb) is a bad idea. Of course System.out.println(...) or log.error(...) really isn't much better. Typically the user should be informed that something they have done has resulted in an error on the server, and at the very least ask them to try again. We've all seen pages like the following: An error has occurred, please try again. If the error continues, please contact the webmaster / admin / whatever. This is a cop out and typically a sign of poor exception handling. At least the user didn't see that nasty stack trace or the 500 page from the server. If it's being left up to the user to make contact about an error, chances are it won't happen and the development team probably won't hear about it. Enter the debate about handling those exceptions, and being more pro-active about knowing about errors. Covering each of those questions is beyond the scope of this series, but the question about framework help certainly applies!
Built-in Handling
Seam proveds a simple, yet robust solution for integrating your exception handling strategy. Two methods exist out of the box for rudimentary handling: <exception> in pages.xml and annotations directly on application specific exceptions. Dan Allen covers these two options nicely in his book Seam in Action section 3.6, (if you don't already own a copy, go get one. It's a life saver) so these will only be briefly reviewed. A third option exists (and the before mentioned options, as well as the powerful Seam Debug page are all built on top of this mechanism) to allow complete customization of display to the end user and actions on the back-end: ExceptionHandler classes.
pages.xml
In a basic seam-gen application one will find the following stanzas of XML relating to exception handling:
<exception class="org.jboss.seam.framework.EntityNotFoundException">
<redirect view-id="/error.xhtml">
<message severity="warn">Record not found</message>
</redirect>
</exception>
<exception class="javax.persistence.EntityNotFoundException">
<redirect view-id="/error.xhtml">
<message severity="warn">Record not found</message>
</redirect>
</exception>
<exception class="javax.persistence.EntityExistsException">
<redirect view-id="/error.xhtml">
<message severity="warn">Duplicate record</message>
</redirect>
</exception>
<exception class="javax.persistence.OptimisticLockException">
<end-conversation/>
<redirect view-id="/error.xhtml">
<message severity="warn">Another user changed the same data, please try again</message>
</redirect>
</exception>
<exception class="org.jboss.seam.security.AuthorizationException">
<redirect view-id="/error.xhtml">
<message severity="error">You don't have permission to access this resource</message>
</redirect>
</exception>
<exception class="org.jboss.seam.security.NotLoggedInException">
<redirect view-id="/login.xhtml">
<message severity="warn">#{messages['org.jboss.seam.NotLoggedIn']}</message>
</redirect>
</exception>
<exception class="javax.faces.application.ViewExpiredException">
<redirect view-id="/error.xhtml">
<message severity="warn">Your session has timed out, please try again</message>
</redirect>
</exception>
<exception class="org.jboss.seam.ConcurrentRequestTimeoutException" log-level="trace">
<http-error error-code="503" />
</exception>
<exception>
<redirect view-id="/error.xhtml">
<message severity="error">Unexpected error, please try again</message>
</redirect>
</exception>
The format is pretty straight forward, a fully qualified class is given in the optional class attribute (leaving this out creates a catch-all handler) and the body is as follows from the XSD:
<xs:element name="exception">
<xs:annotation>
<xs:documentation>A Seam exception handler</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" ref="pages:end-conversation"/>
<xs:choice>
<xs:element ref="pages:http-error"/>
<xs:element ref="pages:redirect"/>
</xs:choice>
</xs:sequence>
<xs:attributeGroup ref="pages:attlist.exception"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="attlist.exception">
<xs:attribute name="class" type="xs:token"/>
<xs:attribute name="log" type="pages:tf-boolean"/>
<xs:attribute name="log-level" type="pages:loglevel-values"/>
</xs:attributeGroup>
Redirects are the typical body of these XML blocks. FacesMessages can be added to the redirect as well as ending conversations. Typically these are used for exceptions the developer does not create, and therefore cannot be annotated; however, there may be uses for this style of handling with application exceptions. Please note that order does matter. If the catch-all handler is first, none of the other handlers will be used. Each of these entries creates an ExceptionHandler instance which is then added to the chain of handlers, which is covered later in the entry.
Annotations
Seam has three annotations to help with exception handling: @Redirect, @HttpError, and @ApplicationException. Only one of @Redirect or @HttpError may be used on an exception. Both allow for an info level FacesMessage to be added via the message attribute. The @Redirect annotation allows input for a view-id to which the user will be redirected. @HttpError simply returns the specified HTTP Error code. The last annotation, @ApplicationException provides the ability to rollback the transaction and end the existing conversation. These annotations are added directly on the Exception class that is created. Both of these built-in methods are built on top of two classes in Seam: org.jboss.seam.exception.Exceptions and org.jboss.seam.exception.ExceptionHandler. These two classes and their usage make up Seam's infrastructure for exception handling in an application, and provide customization to the developer.
Extensible Handling
The above two methods work well for simple cases. What if a team wants to be more pro-active about addressing errors? Could the application send the team emails about exceptions, or create bug tickets, or perhaps create a contextual log entry? This is where the exception handling capabilities of Seam really shine, and the answer to the above questions are all yes!
ExceptionHandler
package org.jboss.seam.exception;
import org.jboss.seam.faces.Navigator;
/**
* An element of the chain that knows how to handle a
* specific exception type.
*
* @author Gavin King
*
*/
public abstract class ExceptionHandler extends Navigator
{
public enum LogLevel { fatal, error, warn, info, debug, trace }
private boolean logEnabled;
private LogLevel logLevel;
public abstract void handle(Exception e) throws Exception;
public abstract boolean isHandler(Exception e);
public boolean isLogEnabled()
{
return logEnabled;
}
public void setLogEnabled(boolean logEnabled)
{
this.logEnabled = logEnabled;
}
public LogLevel getLogLevel()
{
return logLevel;
}
public void setLogLevel(LogLevel logLevel)
{
this.logLevel = logLevel;
}
}
The contract for this class is pretty straight forward. The only methods that need to be implemented are isHandler and handleException. Of course the isHandler implementation is trivial, and based on the needs of the handler the handleException implementation could be fairly simple as well. Take note that ExceptionHandler is a subclass of Navigator. There are methods defined in that class which may be helpful in some exception handlers.
Exceptions
This class is used in the org.jboss.seam.jsf.SeamPhaseListener before and after each phase of the JSF lifecycle and also in the org.jboss.seam.web.ExceptionFilter, wrapping the filter chain, and used again after any redirects that may happen after the filter chain has completed. As Dan Allen described it in Seam in Action: "A try-catch around the [whole request]" (Seam in Action pg. 126). There's only one method that needs any kind of attention: getHandlers. It returns a list that is used to add or remove ExceptionHandlers as needed. This method should be called in the @Create method, or constructor of any ExceptionHandler. ExceptionHandler classes should also be marked with @BypassInterceptors as there's no need to do bi-jection. A simple POJO, though, will typically suffice. Exception handling in Seam can be very powerful if used to it's full potential and should be an excellant tool in crafting an exception handler strategy for your application. The next entry in this series will demonstrate a custom exception handler in action.
|
|
john
|
|
Written by John Larsen
|
|
Tuesday, 29 December 2009 19:21 |
|
We are welcoming the New Year with some new product upgrades. This past year was a rough year for many of us due to shortcomings in the global economy. We shall not dwell on the past! At Javapipe we shall plow ahead with optimism for the future of the JAVA hosting industry. Our goal this year is to provide a solid, maintainable and scalable platform for our present and future clients. Javapipe will provide you with a wider spectrum of solutions and will assist you to meet a variety of objectives that your business might require.
Our solutions will cover the following:
- LAMP for PHP/MySQL objectives. LAMP stands for Linux, Apache (web server), MySQL, and PHP.
- Ruby Enterprise to accommodate the growing popularity of Ruby on Rails. Ruby is included with our LAMP hosting solution.
- Dedicated Apache Tomcat hosting as always. We shall continue to provide the "cream of the crop" in this area!
- Remote MySQL Server solution. Great for more involved MySQL-based websites where local shared MySQL solution just simply doesn't cut it any longer.
- Managed Server solutions. We are now posting inventory for lease. We manage these servers for you and will setup the JAVA server environments to meet your objectives. We can also split up a server to utilize Virtual Servers for better server resource utilization. Each quad core server can handle 4 Virtual Servers and rest assured that they come with enough RAM to satisfy your application demands. Managed servers will provide you with plenty of flexibility, better security, ability to run JBOSS, Glassfish, Weblogic, Websphere, and Oracle Database. (any licensing will be customer's sole responsibility)
- Uncapped 100mbit bandwith solutions with our managed servers. This provides ideal bandwidth for customers who simply have an extremely popular site or wish to provide upload/download solutions to the masses.
Lastly, changes to our existing Apache Tomcat hosting packages. We have decided to do away with our Starter, Basic, Growth and Advanced packages and instead provide our clients with one package with Ram allocation flexibility! Our hope is to simplify the products to allow you a more flexible configuration based on your business needs and objectives. Upgrades are $6/month per 32MB of RAM. You may also upgrade your disk space for $5.95/month per 5GB. All JAVA hosting servers utilize RAID protected storage. We are aware that RAID is not 100% fault tolerant and therefore, does not protect your data fully against corruption! As a result, we offer remote daily backups for $5/mo per 5GB of storage. This backup solution keeps 7 days of backups to safe guard your valuable data.
As always, it's a pleasure to serve you all! Keep in mind that we do not see you as our clients but rather our business partners. Your success is our success!
We wish you a happy and a prosperous new year in 2010! |
|
john
|
|
Written by Sales
|
|
Wednesday, 25 November 2009 19:44 |
|
It's Black Friday week! Black Friday deals now!
Free hosting for the first 3 months with our LAMP or JAVA packages.
How to take advantage of this:
- Sign up for new hosting package.
- Select quarterly billing cycle.
- For enter blackfriday09 for your promotional code.
- Complete the order and you're ready to go.
LAMP hosting includes free domain registration.
Promotion expires Sunday November 29th. |
|
john
|
|
Written by John Larsen
|
|
Saturday, 21 November 2009 08:17 |
|
Watch for special Black Friday hosting deal this Friday November 27th! |
|
john
|
|
Written by John Larsen
|
|
Sunday, 08 November 2009 11:18 |
|
Ruby Enterprise with Ruby on Rails is now available in our LAMP Solution. Ruby Enterprise is another branch of Ruby which focuses more on performance and better memory management. To find out more about Ruby Enterprise, click here.
What you can do with Ruby on Rails via your Iworx control panel
- Create Ruby on Rails Application
- Upload existing Ruby on Rails Application
- Rake a Ruby on Rails Application
- Restart a Ruby on Rails Application
- View Ruby on Rails Application logs
- Install/Uninstall Gems
|
|
john
|
|
Written by John Larsen
|
|
Sunday, 01 November 2009 15:46 |
|
We are offering LAMP hosting at competitive pricing. What is LAMP hosting? It is basically hosting with open source solutions such as LINUX, Apache web server, MySQL database and PHP. On top of that we offering multiple domain hosting and you can host up to 5 domains with our first LAMP hosting solution. You can also easily upgrade your account to Apache Tomcat hosting in the future or vice versa. We believe you will appreciate this flexibility because nobody likes to jump from host to host to meet their objectives!
LAMP A includes 5gb of raid protected storage, multiple domain hosting, unlimited email and ftp account and the option to upgrade to Tomcat hosting at any time.
One more thing... Dozens of installable applications to choose from brought to you by Softaculous. You can access these scripts from within your Siteworx control panel. Applications like Joomla, PHPBB, SugarCRM and many others. They also provide an easy means to upgrade to stay current with security and new features. |
|
john
|
|
Written by Masoud Abbasi
|
|
Thursday, 29 October 2009 13:38 |
|
I find it hard to believe that Internet is 40 years old today! It has definitely come a long way and each and every one us regardless of what we use it for have been involved in defining, shaping and improving it to the point it is today. There are days that I wonder how we used to live without it. Internet today is the true manifestation of the "information super highway" that once we only dreamed of. In the world of entertainment, it has become an important and viable resource. Having access to unlimited number of games, watching movies, listening to music and joining chat rooms, all from the comfort of our leaving rooms! Finding and purchasing products across the globe and utilizing services such as banking, purchasing tickets, reserving hotels, or looking for a job in a matter of minutes would've never been possible without Internet. What a fantastic experience!
Happy 40th Birthday! |
|
john
|
|
Written by John Larsen
|
|
Saturday, 24 October 2009 10:04 |
|
We are now offering our affiliate program to the public. If you are not currently a Javapipe customer, you can now make money sending us referrals right from your website. We are offering $10 affiliate sign-up bonus and 10% commission on all income generated by your referral. Payouts are $50+ and the customer you refer is required to remain a customer for 31 days. The reason for this is to allow customer their 30 day money back guarantee.
If you are interested, please follow this link to register. If you are an existing Javapipe customer, you can sign up from your client area account. We pay 3 ways, paypal, check or credit towards your existing services.
This is a great way for you to generate extra cash from your website and and support your favorite JAVA Hosting company.
To participate in our affiliation program, please log into your client area account and click on the link on the right: Affiliatesand follow instructions. You will be presented with some banners you may use on your website. If you are not a customer, you must register with us before you can take advantage of this program. Please click here to register
If you have any questions, feel free to send us email at
This e-mail address is being protected from spambots. You need JavaScript enabled to view it
|
|
jason
|
|
Written by jason
|
|
Saturday, 12 September 2009 00:00 |
|
Over the past few days I've been working on getting HornetQ (http://www.hornetq.org) to work on Jetty (http://www.mortbay.org/jetty/) -- specifically the embedded Jetty that Gradle (http://www.gradle.org) uses. I would first like to thank those on the HornetQ irc channel (irc://freenode.net:6667/hornetq) for helping me out and offering advice. Specifically I would like to thank Clebert Suconic and Andy Taylor for looking at some of my code and making suggestions that ultimately led me to this solution. It should be noted that the two solutions I will be discussing here are probably not the only roads to success. I'm quite confident the same could be achieved programmatically by setting up HornetQ in a bean that's loaded at application deploy time or similar fashion.
HornetQ setup using jetty-env.xml
Both of my two solutions are using jetty-env.xml to call the needed setup functions for HornetQ. The same could be achieved with jetty.xml if deploying to a standard install of Jetty. More information about these configuration files can be found at http://docs.codehaus.org/display/JETTY/Configuring+Jetty. In short these files act as an XML means of working with Java objects. Objects can be instantiated, methods called, etc. All that's being done here is calling the methods in the HornetQ API to startup HornetQ in Embedded mode. Below is the jetty-env.xml I used:
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure id="wac" class="org.mortbay.jetty.webapp.WebAppContext">
<New id="jmsServerManager" class="org.mortbay.jetty.plus.naming.Resource">
<Arg><Ref id="wac"/></Arg>
<Arg>jms/serverManager</Arg>
<Arg>
<New class="org.hornetq.jms.server.impl.JMSServerManagerImpl">
<Arg>
<Call class="org.hornetq.core.server.HornetQ" name="newHornetQServer">
<Arg>
<New class="org.hornetq.core.config.impl.ConfigurationImpl">
<Set name="persistenceEnabled">false</Set>
<Set name="securityEnabled">false</Set>
<Get name="AcceptorConfigurations">
<Call name="add">
<Arg>
<New class="org.hornetq.core.config.TransportConfiguration">
<Arg>org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory</Arg>
</New>
</Arg>
</Call>
</Get>
</New>
</Arg>
</Call>
</Arg>
<Call name="start" />
<Call name="createConnectionFactory">
<Arg>HornetQConnectionFactory</Arg>
<Arg>
<New class="org.hornetq.core.config.TransportConfiguration">
<Arg>org.hornetq.core.remoting.impl.invm.InVMConnectorFactory</Arg>
</New>
</Arg>
<Arg>
<New class="java.util.ArrayList">
<Call name="add">
<Arg>java:comp/env/jms/connectionFactory</Arg>
</Call>
</New>
</Arg>
</Call>
<Set name="context">
<New class="javax.naming.InitialContext">
</New>
</Set>
<Call name="createQueue">
<Arg>testQueue</Arg>
<Arg>java:comp/env/jms/queues/testQueue</Arg>
<Arg></Arg>
<Arg type="boolean">false</Arg>
</Call>
</New>
</Arg>
</New>
</Configure>
An instance of JMSServerManager is being created and the needed configuration objects are being created inline in this example. It's very important to make the start call on the JMSServerManager before any other calls on the object to create queues, topics or connection factories are made, otherwise you'll get exceptions in your log saying the server hasn't been started yet. It's also important to make sure the full JNDI names are used. jetty-env.xml is used to bind elements to JNDI for you but because the JMSServerManager will be doing the binding for us I found that the full JNDI name must be used. If programmatic access to the JMSServerManager is needed this is also bound to JNDI for us by Jetty under jms/serverManager -- which doesn't use the full JNDI name because Jetty is handling the binding, a slight bit confusing I know. Work with JMS can now proceed using standard JNDI lookups and JMS code to send and receive messages. All of this code is available at my GitHub repo: http://github.com/LightGuard/Research---Development--JEE-/tree/hornetq feel free to check it out, fork it, whatever :)
HornetQ setup using jetty-env.xml and HornetQ configuration files
This setup is very similar to one above, only using the HornetQ configuration files. Code is located at http://github.com/LightGuard/Research---Development--JEE-/tree/hornetq-with-config-file. Here's the jetty-env.xml file:
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure id="wac" class="org.mortbay.jetty.webapp.WebAppContext">
<New id="jmsServerManager" class="org.mortbay.jetty.plus.naming.Resource">
<Arg><Ref id="wac"/></Arg>
<Arg>jms/serverManager</Arg>
<Arg>
<New class="org.hornetq.jms.server.impl.JMSServerManagerImpl">
<Arg>
<Call class="org.hornetq.core.server.HornetQ" name="newHornetQServer">
<Arg>
<New class="org.hornetq.core.config.impl.FileConfiguration">
<Set name="configurationUrl">hornetq-configuration.xml</Set>
<Call name="start" />
</New>
</Arg>
</Call>
</Arg>
<Arg>hornetq-jms.xml</Arg>
<Call name="start" />
<Set name="context">
<New class="javax.naming.InitialContext">
</New>
</Set>
</New>
</Arg>
</New>
</Configure>
It's much smaller this time as most of the configuration has been moved into the hornetq-configuration.xml and hornetq-jms.xml files (both of which are on GitHub). That's really all there is to it! My next steps will be to get logging of hornetq (and hopefully Jetty) using log4j and same log file as the rest of the application.
|
|
|
|
|
<< Start < Prev 1 2 Next > End >>
|
|
Page 1 of 2 |
|
|
|