DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest Frameworks Topics

article thumbnail
Extract constants from strings and numbers with Eclipse refactorings
For readability’s sake, it’s almost always a good idea to replace magic numbers and string literals with constants. That’s all good, but it can take a bit of time to refactor these to constants, especially strings or parts of strings. For example, in the code below we want to refactor “shovel and spade” to a private static final String called TOOLS. To do that manually would take some time. It goes even slower if we only want to extract “spade” to a constant because we first have to convert the string to a concatenation. String tools = "shovel and spade"; ... String otherTools = "shovel and spade"; Luckily, Eclipse has a couple of ways to instantly convert literals to constants. Coupled with tools to speed up string selection and to pick out part of a string, you have the ability to create a constant in about 2 seconds flat. I’ll discuss all these features below. Extract a constant from a string/number There are 2 ways to extract a constant, the one uses a quick fix and the other a refactoring. I’ll show the quick fix method first and then the refactoring and discuss the (small) differences between the two. The example uses a string, but everything is true for numbers as well. Follow these steps to use the quick fix: First select the string. The fastest way is to place the cursor on the string and press Alt+Shift+Up (Select Enclosing Element; a nifty shortcut that I discuss in Select strings and methods with a single keystroke). After selecting the string, press Ctr+1 (Quick Fix) and then select Extract to constant. Eclipse will do the following: (a) Create a private final static variable of type String with a default name, (b) replace all occurrences of that string with the constant and (c) place the cursor on the constant’s declaration to give you a chance to change the name, type and visibility of the variable using placeholders that you can Tab through. Once you’re happy with the constant details, press Enter to go back to the line on which you initiated the quick fix. Here’s a short video with an example of using quick fix. We’ll extract a constant (called TOOLS) from a string literal (“shovel and spade”) that’s used in two places. Note: You can use Tab to move from one placeholder to another and pressing Enter will get you back to your original line. The other way to extract a constant is by using the Extract Constant refactoring. Again, select the string, then select Refactor > Extract Constant… (Alt+T, A) from the application menu. A dialog appears prompting you for the constant’s name, its visibility and whether to replace all occurrences of the string with the constant. After you’ve entered the details, press Enter and you’ll have your constant defined. Here’s a short video with an example using refactoring. We’ll use the same example as above. The differences between the two? Not much, the biggest difference being when you enter the details of the constant (ie. before the change is made or after). The refactoring dialog also provides an option to add the qualifying type name before the constant’s usage, but most of time this is redundant. I’d recommend using the quick fix, unless you’re more comfortable with dialogs. BTW, you can assign custom keyboard shortcuts to either command by mapping either Quick Assist – Extract Constant or the command Extract Constant. Pick out part of a string Sometimes you’ll want to break up a string into multiple parts and convert one of those parts into a constant. Eclipse can do this automatically. Select the part of the string you want to pick out (don’t worry about quotes), press Ctrl+1 and choose Pick out selected part of String. Eclipse will convert that part into a string with quotes, concatenate it to the rest of the string and select it. You can then use any of the Extract Constant tools above. Here’s an example of how to use this feature. Notice how the string’s already selected so we can use the Extract Constant quick fix immediately. Related Tips Select entire strings and methods in Eclipse with a single keystroke Convert string concatenations into StringBuilder or MessageFormat calls with Eclipse’s Quick Fix How to manage keyboard shortcuts in Eclipse and why you should Join/split if statements and rearrange expressions using Eclipse Quick Fix More tips on using quick fixes and making editing faster.
April 19, 2010
by Byron M
· 21,598 Views · 1 Like
article thumbnail
Using Hibernate Validator to Cover Your Validation Needs
Recently I had to choose a validation framework or write one by myself. First I thought, no big deal, validation is not a complicated issue. But the more you think about it, the more you come to the conclusion that it is not as shallow as you think – you need to validate different types, you have different groups and many more issues… In short, writing a validation framework by yourself demands a lot of work. Luckily, JSR 303 solves this and the Hibernate implementation of the JSR does a pretty good job. Hibernate Validator is a JSR 303 implementation for bean validation. The way to work with this framework is first, to define constraints for java bean fields, and then, validating the bean. JSR 303 JSR 303 – defines a metadata model and API for entity validation. The default metadata source is annotations, with the ability to override and extend the meta-data through the use of XML. The API is not tied to a specific application tier or programming model. It is specifically not tied to either the web tier or the persistence tier, and is available for both server-side application programming, as well as for rich client Swing application developers. Hibernate Validator features Defining validation data using annotation and/or XML. Full object validation (including inner objects using recursion) Create customized constraints and validators. Customized error messages. Define groups(profiles). Create a Traversable Resolver. Using constraints Using XML Here is a simple example of a constraint using xml: com.mytest 2 In this example the field x can not be null. The field y can not be less than 2. Notice that the “Min” constraint has inner element – “value”. Notice the tag “”. It indicates the root path of all the beans. See also directions on how to load the XML file while using the validator. Using annotations Here is a simple code example: public class MyBean{@NotNullString x;@Min(2)int y;} This example is the equivalent to the previous xml example. Using both Using both annotations and XML constraints is possible. By default if you are using both only the XML is taken, unless you are using the attribute ‘ignore-annotations’ in the XML. Example: com.mytest.beans 2 2 Notice that the attribute ignore-annotations appears twice – for a bean and for a field. The default for a bean is ignore-annotations=”true” – this means that if you have an XML constraint for a bean, it will cancel the attribute constraint, Unless you will indicate that by ignore-annotations=”false” (look at the example). The default for a field is ignore-annotations=”false”. This means that by default annotations for a field are stronger (this is of course after you indicated that that the bean itself wont ignore annotations). If you wont that the XML will be stronger than you have to indicate that by ignore-annotations=”true” (look at the example in the “x2″ constraint). Existing constraints These constraints are a part of the hibernate validation framework: Constraint path Parameters javax.validation.constraints.AssertTrue (none) javax.validation.constraints.AssertFalse (none) javax.validation.constraints.NotNull (none) javax.validation.constraints.Null (none) javax.validation.constraints.Max value(mandatory) javax.validation.constraints.Min value(mandatory) javax.validation.constraints.DecimalMax value(mandatory) javax.validation.constraints.DecimalMin value(mandatory) javax.validation.constraints.Pattern regexp(mandatory) flags(optional) javax.validation.constraints.Past (none) javax.validation.constraints.Future (none) javax.validation.constraints.Size min(optional) max(optional) javax.validation.constraints.Digits integer(mandatory) fraction(mandatory) org.hibernate.constraints.Email (none) org.hibernate.constraints.Length min(optional) max(optional) org.hibernate.constraints.NotEmpty (none) org.hibernate.constraints.Range min(optional) max(optional) Inner objects constraints If you have nested beans (beans which contain other beans) you can easily let the system validate also the inner objects by using the constraint ‘valid’. XML example: com.mytest.beans Annotation example: public class MyBean{@Valid //inner bean to be validated separatelyprivate InnerBean innerBean; public InnerBean getInnerBean() {return innerBean;}public void setInnerBean(InnerBean innerBean) {this.innerBean = innerBean;}public class InnerBean { @NotNullString xx; public String getXx() {return xx;}public void setXx(String xx) {this.xx = xx;} Validating Example of a simple validation: ValidatorFactory factory = Validation.buildDefaultValidatorFactory();Validator validator = factory.getValidator();Set> constraintViolations = validator.validate(bean); Loading a constraints XML file As mentioned, you don’t have to use an XML file for defining constraints, you can just use annotations. But if you do want an XML file, you will have to load the file. Example: Configuration config = Validation.byDefaultProvider().configure();FileInputStream in = new FileInputStream( new File("resources/demo-constraints.xml"));config.addMapping(in);// Building the customized factory// (along with the changed configuration)ValidatorFactory factory = config.buildValidatorFactory();Validator validator = factory.getValidator(); The result The result(as you can see in the example above) is a collection of ConstraintViolation. Each ConstraintViolation holds the problematic field, it’s value and the error message itself. Example of reading the result: Set> constraintViolations = validator.validate(bean);//printing the resultsfor (ConstraintViolation constraintViolation : constraintViolations) {System.out.println(constraintViolation.getPropertyPath() + " -> " +constraintViolation.getMessage());} This object can be easily transformed to a more generic object like ValidationException or CyotaSoapException and so on. Customized constraints and validators If you want to create a new constraint you will have to create the constraint annotation interface and the validator class. Creating the constraint interface Here is a simple constraint example @Target( { METHOD, FIELD, ANNOTATION_TYPE })@Retention(RUNTIME)@Constraint(validatedBy = MyValidator.class)@Documentedpublic @interface MyConstraint{// These next parameters exist in every constraintString message() default "{com.mytest.MyConstraint.message}";Class[] groups() default {};Class[] payload() default {};// These next parameters are added// They are the constraint's attributesString myOptionalValue() default ""; //this parameter has a default valueString myMustValue(); //this parameters need to get input from the user} Notice the @Constraint annotation. It signifies the class that suppose to validates this constraint. Notice the message class member. It holds an error message or, like in this case, an error code. It will later be interpreted as a literal error message. The payload member holds payload objects. These objects carry additional data attached to the constraints that can be fetched when validating. Nested constraints You can also overload constraints very easily. For example, let’s say I want to create a new constraint which also checks that the value is not null. In this case, all I have to do is this: @Target( { METHOD, FIELD, ANNOTATION_TYPE })@Retention(RUNTIME)@Constraint(validatedBy = MyValidator.class)@Documented@NotNullpublic @interface MyConstraint{String message() default "{com.mytest.MyConstraint.message}";Class[] groups() default {};Class[] payload() default {};} In the example, notice the @NotNull annotation. Creating the validator class Here is an example of a simple validator: public class MyValidatorimplements ConstraintValidator {MyConstraint MyConstraint;/** * This function recives the constraint instance * (along with the user values) */public void initialize(MyConstraint MyConstraint) {this.MyConstraint=MyConstraint;}/** * The value is the actual object instance. * */public boolean isValid(String value, ConstraintValidatorContext arg1) { //using input from the userreturn value!=null && value.startsWith(MyConstraint.myMustValue());} The above code shows an example of a validator which validates that the value of the given string starts with a given character. The validator implements the ConstraintValidator interface. Notice that the constraint is given as input to the initialize() function. The value itself is input to the isValid() function Customizing error messages Each error has an error template. The error template is defined in the constraint annotation interface. This error template is later translated into an error message. The actual error message may be defined in 2 places: 1. Inside the constraint deceleration. The error message be defined when defining the constraint, whether it you are using XML or annotations. XML example: x is too small 2 Java example: public class MyBean{@Min(value = 2, message="x is too small")private String x;public String getX() {return x;}public void setX(String x) {this.x = x;} 2. Using a separate properties message. You may want to load a separate properties file containing the error messages according to the error template. loading the messages properties file is done using the validation factory configuration: Configuration config = Validation.byDefaultProvider().configure();// Using a properties file for customized error messagesFileInputStream in = new FileInputStream(new File("resources/messages.properties"));ResourceBundleMessageInterpolator messageInterpolator =new ResourceBundleMessageInterpolator( new PropertyResourceBundle(in));// Setting a messages properties fileconfig.messageInterpolator(messageInterpolator);in = new FileInputStream(new File("resources/demo-constraints.xml"));config.addMapping(in);// Building the customized factory (along with the changed configuration)ValidatorFactory factory = config.buildValidatorFactory();Validator validator = factory.getValidator(); Using groups There may be occasions when you will want to create a single constraint but with different values for different situations. For example, let’s say you want to create a username field and let him a minimum constraint. But, one time it will have minimum of 5 characters and another time it will have minimum of 6 characters. For cases like this you will want to use groups. To do so, you will have to create a group, create constraints for that group and last, validate objects by attaching the group. Please follow the steps below Create a group To create a group you simply create a new interface. example: public interface MyBeanGroup{} Create a constraint for the group XML example: com.mytest.groups.MyBeanGroup Annotations example: public class MyBean{@NotNull(groups = MyBeanGroup.class)private String x; public String getX() {return x;}public void setX(String x) {this.x = x;} Validate an object using the group Set> constraintViolations = validator.validate(bean, MyBeanGroup.class); The default group The default group is javax.validation.groups.Default. If you don’t assign a constraint any group it applies to the default group. If you are validating an object without using any group, it is validated as a part of the default group. Groups inheritance You can also create an group inheritance tree. In this way, if you validate an object using a group it will prefer constraints that are defined to it. But if there are no such constraints, then it will also take the constraints of it’s parents. Example, this is a group which inherits the default group: public interface MyBeanGroupextends javax.validation.groups.Default{} All the constraints that are defined for that group will apply to it. But also all the constraints which do not apply to any group(and by which apply to the default group), will also apply to it, since it exteds the default group. Jar dependency validation-api-1.0.0.GA.jar hibernate-validator-4.0.2.GA slf4j-api-1.4.2.jar slf4j-simple-1.4.2.jar log4j-1.2.15.jar Only for java5 jaxb-xjc-2.1.6.jar jaxb-impl-2.1.6.jar jaxb-api-2.1.jar activation-1.1.jar geronimo-stax-api_1.0_spec-1.0.1.jar References JSR 303 specification- Bean validation Product main page Hibernate Validator documentation Download demo project from http://www.aviyehuda.com/
April 15, 2010
by Avi Yehuda
· 134,335 Views
article thumbnail
What's New in VS2010 and .Net 4?
Today marks a critical turning point for Microsoft as they announce the final releases of Visual Studio 2010, the .Net Framework 4.0, and Silverlight 4 (available later this week). With .Net 4, Microsoft is simplifying parallel programming and adding a broader range of language choices. Visual Studio 2010 is a major improvement over the 2008 version. VS 2010 includes support for Windows 7, Windows Azure, and tools for building applications on top of Microsoft Sharepoint. Here are some of the new features for VS 2010 and the .Net 4 platform: Visual Studio 2010 VS 2010 has something for just about everybody. Mobile developers who want to get a head start on developing applications for the Windows Phone 7 OS can use the integrated phone design surfaces available in Microsoft's IDE. Developers can also deliver expressive user experiences through the Windows 7 multitouch and “ribbon” interfaces. This release of Visual Studio is also the first to give developers integrated access to SharePoint functionality. The first thing that developers will notice is a new editor, shell, and Managed Extensibility Framework in Windows Presentation Foundation (WPF). Developers with multiple monitors will be able to "float" windows from one display to another. The Premium and Ultimate editions also include standard UML diagramming. New WPF Interface Floating Windows VS 2010's IDE for editing C++ (Visual C++ 2010) now supports functionality and library components from the C++0z standard. These features include compile-time assertions, lambda expressions, rvalue references, and the auto keyword for type inference. Visual C++ also has much improved (and simplified) support for parallel programming with a new Concurrency Runtime that schedules and manages parallel loads. The Dotfuscator is a third-party tool bundled with Visual Studio 2010 that was originally designed to obscure .Net code. The obfuscation of .Net code is necessary to prevent decompilation by other parties. Along with this feature, the new Dotfuscator also includes Runtime Intelligence Support, which adds analytics support for your desktop application code. This lets developers log data (on a hosted portal or your own server) on how the application is being used. Along with tamper detection, developers can also use the Dotfuscator to set expiration dates for free application trials and subscriptions. Dotfuscator Instrumentation Options Modern testing and code review are seeing a rise in 'replay' tools that make it easier to reproduce bugs that are hard to find. VS 2010 includes a new tool called IntelliTrace, which allows developers to record video of an application at the time when a defect manifests. Tools like these will be essential for improving QA efficiency. Visual Studio 2010 also comes with a vast array of web development tools. It ships with ASP.NET MVC 2.0 and the older Web Forms framework. VS 2010's built-in test framework for ASP.NET reminds developers when they should create tests as they're working. Another aspect of VS 2010's web development is RIA Services, which is a part of WCF that simplifies authentication and read-write data access in Silverlight or ASP.NET applications. With the recent launch of Windows Azure, VS 2010 is the first IDE to come with Azure project types. Developers will need to download the Azure SDK and tools separately. Currently, these tools have not reached their final versions. Here is a snapshot of the three VS 2010 editions available: Visual Studio 2010 Ultimate with MSDN, featuring the full suite of tools including ALM products. Testing and architecture tools also are featured. It carries a price tag of $11,924 for a new customer and $3,841 for a current customer renewing with Microsoft. Visual Studio 2010 Premium with MSDN, featuring the Visual Studio toolset but lacking some architecture capabilities of the Ultimate edition. Some of Microsoft's ALM suite is included. Premium costs $5,469 for new users and $2,299 for customers seeking renewals. Visual Studio 2010 Professional with MSDN, for basic development tasks. It includes the core version of Visual Studio. It costs $1,199 for a new user and $799 for a renewal. Users also can purchase Visual Studio 2010 Professional minus a MSDN subscription for $799. .Net 4 The .Net Framework 4.0 includes new programming models, languages, and various features that have prepared the platform for modern development. The Dynamic Language Runtime is a major step for .Net that adds a set of dynamic language services to the CLR (Common Language Runtime). This makes it easier to develop dynamic languages for .Net and add dynamic features to statically typed languages. .Net 4 introduces a new programming model that simplifies multithreaded and asynchronous programming in application and library development. Developers can write scalable parallel code using a natural idiom without having to work directly with threads or the thread pool. There is also a parallel implementation of LINQ to Objects (PLINQ). An important feature for backward compatibility is side-by side hosting, which allows developers to run applications based on older .Net frameworks in the same process as .Net 4 applications. The .Net 4 Framework also provides garbage collection in the background. .Net 4 features a revamp of Windows Workflow and some new language features. Along with C#, VB.Net, IronRuby, and IronPython, there is also a new language in .Net 4 called F#. F# is a multi-paradigm language that is aimed at bringing functional programming into mainstream enterprise development. One of the biggest enhancements of the .Net Framework 4 is the reduction in client footprint by more than 80 percent. • To download, purchase or get more information on Visual Studio 2010: http://www.microsoft.com/visualstudio • To download or get more information on the .NET Framework: http://www.microsoft.com/net
April 12, 2010
by Mitch Pronschinske
· 23,833 Views
article thumbnail
Share Eclipse Perspective Layouts Across Multiple Workspaces
once you’ve configured eclipse preferences to your heart’s content, you’ll often want to share those preferences across multiple workspaces. now normally you can go to file > export > general > preferences to save your preferences to a properties file which you can then import into the other workspace. this will share settings such as your customised keyboard shortcuts, formatting, repository settings, etc. but, for some reason, eclipse doesn’t save perspective/window layouts, such as which views are open and where they are placed in the perspective. so you’ll find yourself spending another half hour configuring the window to the way you like it. after the 3rd workspace you need to create, this becomes frustrating and just wastes time. fortunately there are ways to save and restore these settings automatically. the first is to save the perspective into the preferences and the other is to use eclipse’s copy settings feature when opening the other workspace. i prefer the first option, but i’ll mention the second option and when to use the one over the other. method 1: save the layout as a new perspective the first method is to save the perspective layout as another perspective, then export the preferences file as normal. the saved perspective’s settings will be included in the preferences file. when you’ve updated the layout, just resave and overwrite the perspective and export the preferences again. to save your perspective, select window > save perspective as… from the application menu. a dialog should popup (shown below), prompting you for a perspective name. enter a name that you’ll remember, eg. my java or debug jack . click ok once you’ve entered a new name. note : you can choose to overwrite one of the default perspectives, eg. java , without fear. however, i prefer to leave these intact, so always choose a new name, but you can choose whatever works for you. now you can go through the normal routine of exporting the preferences to a properties file via file > export > general > preferences . then import the same file in another workspace via file > import > general > preferences . all you now have to do is switch over to the perspective you saved and all your layout settings will be restored. if you overwrote one of the default perspectives, you may have to select window > reset perspective… to restore the saved settings. if you’ve chosen to create a new perspective, be sure to point your run/debug settings to the new perspective under window > preferences > run/debug > perspectives . for example, if you made a new perspective based on the debug perspective, then you’ll need to change references to the debug perspective to the my debug for launchers you use. luckily this is only required once as these settings are also saved when you export preferences (at least since eclipse 3.5). gotcha: i use fast views a lot , and for some reason the fast view dock’s position isn’t restored automatically. but manually restoring this is as easy as moving the dock, so it’s not that bad. toolbar settings aren’t saved either, but i haven’t tampered with these a lot anyway since i prefer using the keyboard and mouse gestures. method 2: use copy settings the other method of saving your window layout is to use the copy settings feature when switching to another workspace. to use this feature, first open the workspace that contains your customised layout. then select file > switch workspace > other… which will open a dialog prompting you for an existing/new workspace. select the workspace, then click the copy settings collapsible section. select the workbench layout checkbox and click ok. your workspace will open and should reflect the customised layout of the previous workspace. here’s what the dialog looks like: which method should i use? well, as i said before, i prefer the first method for a number of reasons. if some of these apply to you then you might want to use the first method as well. use this method if: you want to share layout settings across workspaces on different machines, eg. work and home. this method is a lot more portable because you only need one single properties file. you spend 90% of your time in 1 or 2 perspectives (eg. java & debug) then this method works well because you only have to manage those perspectives. you make a lot temporary changes to perspectives that you don’t necessarily want shared. for example, if you’ve opened a number of views that you rarely use, you don’t want to clutter your new workspace with these views. i find that i have my “base” perspective layout, around which things will change depending on the context and i don’t want these to clutter my “base” layout. you want to share preferences with a colleague/friend. use the copy settings method if: you want to quickly create another workspace with the saved layout without having to export any preferences. you have made a number of changes across many perspectives and you want to restore those settings. you’re feeling lazy. with this method, eclipse manages a lot more things, so it’s a bit easier to manage (in the short-term), but for the longer term, the first method is best. from http://eclipseone.wordpress.com
March 26, 2010
by Byron M
· 16,394 Views
article thumbnail
Bean Validation and JSR 303
In this article, I will show you how to use the new Bean Validation Framework aka JSR-303. The legacy Before getting the result that is JSR 303, aka the Bean Validation framework, there were two interesting attempts at validation framework. Each came from an end of the layers and focused on its scope. Front-end validation Struts was the framework to learn and use on the presentation layer in 2001-2002. Struts uses the MVC model and focus on Controllers, which are represented in Struts with Action. Views are plain JSP and Struts uses ActionForm in order to pass data from Controllers to Views and vice-versa. In short, those are POJO that the framework uses to interact with the View. As a presentation layer framework, Struts concern is validating user input. Action forms have a nifty method called validate(). The signature of this method is the following: public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) The developer has to check whether the form is valid then fill the ActionErrors object (basically a List) if it’s not the case. Struts then redirects the flow to an error page (the input) if the ActionErrors object is not empty. Since manual checking is boring and error-prone, it may be a good idea to automate such validation. Even at that time, declarative validation was considered to be the thing. This is the objective of Apache Commons Validator. Its configuration is made through XML. You specify: the validators you have access to. There are some built-in but you can add your own the associations between beans and validators: which beans will be validated by which rules Though Struts tightly integrates Commons Validator, you can use the latter entirely separately. However, the last stable version (1.3.1) was released late 2006. The current developed version is 1.4 but the Maven site hasn’t been updated since early 2008. It is a bit left aside for my own tatse so I rule it out for my validation needs save when I am forced to use Struts. In this case it is mandatory for me to use it since the Struts plugin knows how to use both XML configuration files to also produce JavaScript client-side validation. Back-end validation Previously, we saw that the first validation framework came from user input. At the other end of the specter, inserting/updating data does not require such validation since constraints are enforced in the database. For example, trying to insert a 50 characters length string into a VARCHAR(20) column will fail. However, letting the database handle validation has two main drawbacks: it has a performance cost since you need to connect to the database, send the request and handle the error such error cannot be easily mapped to a Java exception and if possible, to a particular attribute in error In the end, it is better to validate the domain model in the Java world, before sending data to the database. Such was the scope of Hibernate Validator. Whereas Commons Validator configuration is based on XML, Hibernate Validator is based on Java 5 annotations. Even if Hibernate Validator was designed to validate the domain model, you could use it to validate any bean. JSR 303 Bean Validation Finally, JSR 303 came to fruitition. Two important facts: it is end-agnostic, meaning you can use it anywhere you like (front-end, back-end, even DTO if you follow this pattern) and its reference implementation is Hibernate Validator v4. JSR 303 features include: validation on two different levels: attribute or entire bean. That was not possible with Hibernate Validator (since it was database oriented) and only possible with much limitations with Commons Validator i18n ready and message are parameterized extensible with your own validators configurable with annotations or XML. In the following, only the annotation configuration will be shown In JSR 303, validation is the result of the interaction between: the annotation itself. Some come with JSR 303, but you can build your own the class that will validate the annotated bean Simplest example The simplest example possible consist of setting a not-null constraint on an attribute of a class. This is done simply so: public class Person { private String firstName; @NotNull public String getFirstName() { return firstName; } // setter } Note that the @NotNull annotation can be placed on the attribute or on the getter (just like in JPA). If you use Hibernate, it can also use your JSR 303 annotations in order to create/update the database schema. Now, in order to validate an instance of this bean, all you have to do is: Set> violations = validator.validate(person); If the set is empty, the validation succeeded, it not, it failed: the principle is very similar to both previous frameworks. Interestingly enough, the specs enforce that constraints be inherited. So, if a User class inherits from Person, its firstName attribute will have a not-null constraint too. Constraints groups On the presentation tier, it may happen that you have to use the same form bean in two different contexts, such as create and update. In both contexts you have different constraints. For example, when creating your profile, the username is mandatory. When updating, it cannot be changed so there’s no need to validate it. Struts (and its faithful ally Commons Validator) solve this problem by associating the validation rules not with the Java class but with the mapping since its scope is the front-end. This is not possible when using annotations. In order to ease bean reuse, JSR 303 introduce constraint grouping. If you do not specify anything, like previously, your constraint is assigned to the default group, and, when validating, you do so in the default group. You can also specify groups on a constraint like so: public class Person { private String firstName; @NotNull(groups = DummyGroup) public String getFirstName() { return firstName; } // setter } So, this will validate: Person person = new Person(); // Empty set Set> violations = validator.validate(person); This will also: Person person = new Person(); // Empty set Set> violations = validator.validate(person, Default.class); And this won’t: Person person = new Person(); // Size 1 set Set> violations = validator.validate(person, DummyGroup.class); Custom constraint When done playing with the built-in constraints (and the Hibernate extensions), you will probably need to develop your own. It is very easy: constraints are annotations that are themselves annotated with @Constraint. Let’s create a constraint that check for uncapitalized strings: @Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = CapitalizedValidator.class) public @interface Capitalized { String message() default "{ch.frankel.blog.validation.constraints.capitalized}"; Class[] groups() default {}; Class[] payload() default {}; } The 3 elements are respectively for internationalization, grouping (see above) and passing meta-data. These are all mandatory: if not defined, the framework will not work! It is also possible to add more elements, for example to parameterize the validation: the @Min and @Max constraints use this. Notice there’s nothing that prevents constraints from being applied to instances rather than attributes, this is defined by the @Target and is a design choice. Next comes the validation class. It must implement ConstraintValidator: public class CapitalizedValidator implements ConstraintValidator { public void initialize(Capitalized capitalized) {} public boolean isValid(String value, ConstraintValidatorContext context) { return value == null || value.equals(WordUtils.capitalizeFully(value)); } } That’s all! All you have to do now is annotate attributes with @Capitalized and validate instances with the framework. There’s no need to register the freshly created validator. Constraints composition It is encouraged to create simple constraints then compose them to create more complex validation rules. In order to do that, create a new constraint and annotate it with the constraints you want to compose. Let’s create a constraint that will validate that a String is neither null nor uncapitalized: @NotNull @Capitalized @Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = {}) public @interface CapitalizedNotNull { String message() default "{ch.frankel.blog.validation.constraints.capitalized}"; Class[] groups() default {}; Class[] payload() default {}; } Now, annotate your attributes with it and watch the magic happen! Of course, if you want to prevent constraint composition, you’ll have to restrain the @Target values to exclude ANNOTATION_TYPE. Conclusion This article only brushed the surface of JSR 303. Nevertheless, I hoped it was a nice introduction to its features and gave you the desire to look into it further. You can find here the sources (and more) for this article in Eclipse/Maven format. From http://blog.frankel.ch
March 23, 2010
by Nicolas Fränkel
· 60,681 Views · 1 Like
article thumbnail
Aspect Oriented Programming For Eclipse Plug-ins
It seems to me that Aspect Oriented Programming never really took off when it was introduced. However, it's a useful way to intercept, or analyse, methods as they happen, in an independent way. Eclipse has a useful suite of AspectJ tools that you can download for your Eclipse installlation. Paired with the benefits of Eclipse's plug-in system, aspects are a nice way of intercepting your RCP application. The following instructions show how to get up and running with aspects in the Plug-in Development Environment really quickly. Once you have downloaded the Eclipse AspectJ tools, you will also want to include the Equinox Aspect jars in your plug-ins directory. The plug-ins you will need are org.eclipse.equinox.weaving.aspectj and org.eclipse.equinox.weaving.hook Create a new OSGi plug-in: Right click on the project and choose AspectJ Tools/Convert to AspectJ Project Create a new package within the plugin eg. com.dzone.aspects.aspectTest Make a new aspectj Aspect within the package e.g. MyAspect In your manifest.mf export the package created in the previous step Export-Package: com.dzone.aspects A you write your AspectJ code, you will be advising another plug-in (for example org.eclipse.jdt.junit) You'll need to do some extra setup in order to advise other plug-ins, by adding the following to your Aspect plug-in manifest.mf. Eclipse-SupplementBundle: org.eclipse.jdt.junit Note you can only supplement one bundle in an aspect. Therefore, if you want to crosscut another bundle, you’ll need to create a new AspectJ plug-in. It also helps to add the plugin that you are advising (org.eclipse.jdt.junit) to your aspect plugin's dependencies. If you don't do it you will get lint warnings from the AspectJ compiler In your plugins META-INF directory make a file called aop.xml, consisting of content similar to the following When executing use the following VM arguments in your Run Configuration -Dosgi.framework.extensions=org.eclipse.equinox.weaving.hook -Dorg.aspectj.osgi.verbose=true It's as simple as that. Have you any instructions to add to this?
March 23, 2010
by James Sugrue
· 10,784 Views
article thumbnail
Play! Framework Usability
Perhaps the most striking thing about about the Play! framework is that its biggest advantage over other Java web application development frameworks does not fit into a neat feature list, and is only apparent after you have used it to build something. That advantage is usability. Note that usability is separate from functionality. In what follows, I am not suggesting that you cannot do this in some other framework: I merely claim that it is easier and more pleasant in Play! I need to emphasise this because geeks often have a total blind spot for usability because they enjoying figuring out difficult things, and under-appreciate the value of things that Just Work. Written by web developers for web developers The first hint that something different is going on here is when you first hear that the Play! framework is 'written by web developers for web developers', an unconventional positioning that puts the web's principles and conventions first and Java's second. Specifically, this means that the Play! framework is more in line with the W3C's Architecture of the World Wide Web than it is with Java Enterprise Edition (Java EE) conventions. URLs for perfectionists For example, the Play! framework, like other modern web frameworks, provides first-class support for arbitrary 'clean' URLs, which has always been lacking from the Servlet API. It is no coincidence that at the time of writing, Struts URLs for perfectionists, a set of work-arounds for the Servlet API-based Struts 1.x web framework, remains the third-most popular out of 160 articles on www.lunatech-research.com despite being a 2005 article about a previous-generation Java web technology. In Servlet-based frameworks, the Servlet API does not provide useful URL-routing support; Servlet-based frameworks configure web.xml to forward all requests to a single controller Servlet, and then implement URL routing in the framework, with additional configuration. At this point, it does not matter whether the Servlet API was ever intended to solve the URL-routing problem and failed by not being powerful enough, or whether it was intended to be a lower-level API that you do not build web applications in directly. Either way, the result is the same: web frameworks add an additional layer on top of the Servlet API, itself a layer on top of HTTP. Play! combines the web framework, HTTP API and the HTTP server, which allows it to implement the same thing more directly with fewer layers and a single URL routing configuration. This configuration, like Groovy's and Cake PHP's, reflects the structure of an HTTP request - HTTP method, URL path, and then the mapping: # Play! 'routes' configuration file… # Method URL path Controller GET / Application.index GET /about Application.about POST /item Item.addItem GET /item/{id} Item.getItem GET /item/{id}.pdf Item.getItemPdf In this example, there is more than one controller. We also see the use of an id URL parameter in the last two URLs. HttpServletRequest Another example is Play!'s Http.Request class, which is a far simpler than the Servlet API's HttpServletRequest interface. In addition, Play! uses a class where Java EE 6 uses the Java EE convention of using an interface. This interface is also split between HttpServletRequest and the more generic ServletRequest interface. This separation may be useful if you want to use Servlets for things other than web applications, or if you want to allow for the unlikely possibility of the web changing protocol, but for most of us it is merely irrelevant complexity. In other words, the Servlet API is always used with a framework on top these days because it is sub-optimised for building web applications, which is what all of us actually use it for. Play! fixes that. Better usability is not just for normal people Another way of looking at the idea that Play! is by and for web developers is to consider how a web developer might approach software design differently to a Java EE developer. When you write software, what is the primary interface? If you are a web developer, the primary interface is a web-based user-interface constructed with HTML, CSS and (increasingly) JavaScript. A Java EE developer, on the other hand, may consider their primary interface to be a Java API, or perhaps a web services API, for use by other layers in the system. This difference is a big deal, because a Java interface is intended for use by other programmers, while a web user-interface interface is intended for use by non-programmers. In both cases, good design includes usability, but usability for normal people is not the same as usability for programmers. In a way, usability for everyone is a higher standard than usability for programmers, when it comes to software, because programmers can cope better with poor usability. This is a bit like the Good Grips kitchen utensils: although they were originally designed to have better usability for elderly people with arthritis, it turns out that making tools easier to hold is better for all users. The Play! framework is different because the usability that you want to achieve in your web application is present in the framework itself. For example, the web interface to things like the framework documentation and error messages shown in the browser is just more usable. Along similar lines, the server's console output avoids the pages full of irrelevant logging and pages of stack traces when there is an error, leaving more focused and more usable information for the web developer. $ play run phase ~ _ _ ~ _ __ | | __ _ _ _| | ~ | '_ \| |/ _' | || |_| ~ | __/|_|\____|\__ (_) ~ |_| |__/ ~ ~ play! 1.0, http://www.playframework.org ~ ~ Ctrl+C to stop ~ Listening for transport dt_socket at address: 8000 10:15:58,629 INFO ~ Starting /Users/peter/Documents/work/workspace/phase 10:16:00,007 WARN ~ You're running Play! in DEV mode 10:16:00,424 INFO ~ Listening for HTTP on port 9000 (Waiting a first request to start) ... 10:16:11,847 INFO ~ Connected to jdbc:hsqldb:mem:playembed 10:16:13,448 INFO ~ Application 'phase' is now started ! 10:16:14,825 INFO ~ starting DispatcherThread 10:16:48,168 ERROR ~ @61lagcl6i Internal Server Error (500) for request GET /application/startprocess?account=x Java exception (In /app/controllers/Application.java around line 41) IllegalArgumentException occured : Person not found for account x play.exceptions.JavaExecutionException: Person not found for account x at play.mvc.ActionInvoker.invoke(ActionInvoker.java:200) at Invocation.HTTP Request(Play!) Caused by: java.lang.IllegalArgumentException: Person not found for account x at controllers.Application.startProcess(Application.java:41) at play.utils.Java.invokeStatic(Java.java:129) at play.mvc.ActionInvoker.invoke(ActionInvoker.java:127) ... 1 more Try to imagine a JSF web application producing a stack trace this short. In fact, Play! goes further: instead of showing the stack trace, the web application shows the last line of code within the application that appears in the stack trace. After all, what you really want to know is where things first went wrong in your own code. This kind of usability does not happen by itself; the Play! framework goes to considerable effort to filter out duplicate and irrelevant information, and focus on what is essential. Quality is in the details In the Play! framework, much of the quality turns out to be in the details: they may be small things individually, rather than big important features, but they add up to result in a more comfortable and more productive development experience. The warm feeling you get when building something with Play! is the absence of the frustration that usually results from fighting the framework. We recommend that you go to http://www.playframework.org/, download the latest binary release, and spend half an hour on the tutorial. Peter Hilton is a senior software developer at Lunatech Research.
March 16, 2010
by $$anonymous$$
· 24,647 Views
article thumbnail
Generate Class Constructors in Eclipse Based on Fields or Superclass Constructors
You’ll often need to add a constructor to a class based on some/all of its fields or even based on constructors of its superclass. Take the following code: public class Contact { private String name, surname; private int age; public Contact(String name, String surname, int age) { this.name = name; this.surname = surname; this.age = age; } } That’s 5 lines of code (lines 5-9) just to have a constructor. You could write them all by hand, but writing a constructor that accepts and initialises each field takes a lot of time and becomes irritating after a while. And creating constructors from a superclass can take even longer because the superclass can define multiple constructors that you need to reimplement. That is why Eclipse has two features to help you generate these constructor instantly: Generate Constructor using Field and Generate Constructor from Superclass. Both features will generate a constructor in seconds, freeing you up to get to the exciting code. You’ll also see how to add/remove/reorder arguments of an existing constructor based on fields defined in the class. Generate a constructor from fields The fastest way to generate a constructor based on fields is to press Alt+Shift+S, O (alternatively select Source > Generate Constructor using Fields… from the application menu). This pops up a dialog where you can select the fields you want to include in the constructor arguments. Once you’ve selected the fields you want, just click Ok and you’re done. BTW, Alt+Shif+S is the shortcut to display a shortened Source menu, allowing Java source editing commands. The following video shows an example of how much time this feature can save you. We’ll create a constructor for the class Message. Notes: You can additionally call a superclass constructor with a subset of the fields by changing the dropdown Select super constructor to invoke at the top of the dialog. This creates a super(…) call with the relevant arguments and initialising code for the rest of the arguments on your subclass’s constructor. If you don’t want the JavaDoc for the constructor, disable the checkbox Generate constructor comments on the dialog. You can include/exclude the calls to super() using the checkbox Omit call to default constructor super(), on the dialog. You have to be positioned in a class to invoke this command. If you use frequently use this command, you can remap its keyboard shortcut by changing the key binding for the command Generate Getters and Setters. Generate constructor(s) from a superclass Sometimes you’ll want to reimplement some/all of a superclass’s constructors, especially as part of the contract. To generate constructor(s) from a superclass, just press Alt+Shift+S, C (or alternatively select Source > Generate Constructor from Superclass… from the application menu). A dialog pops up allowing you to select the constructor(s) you’d like to create. Once you click Ok, Eclipse generates the constructor, together with a super() call. Here’s an example of how to create a constructor in SecretMessage, that inherits from the class Message. Message has three constructors: a default one, one that accepts one String (content) and another that accepts three Strings (content, fromAddress and toAddress). SecretMessage should only expose the last two constructors. Note: You have to be positioned in a class to invoke this command. If you use this command frequently, you can remap its keyboard shortcut by changing the key binding for the command Generate constructors from superclass. Add, reorder and remove fields on existing constructors If you have an existing constructor and want to reorder its arguments or remove some of them, have a look at the Change Method Signature refactoring that does that in a jiffy. If you want to add a single field to an existing constructor, have a look at the next video that uses Eclipse’s Quick Fix (Ctrl+1) to do that easily. I’ll add a field createdDate to an existing constructor in Message by choosing Assign parameter to field from the Quick Fix menu while positioned on the field. From http://eclipseone.wordpress.com
March 9, 2010
by Byron M
· 30,922 Views · 1 Like
article thumbnail
Building a Star Rating System with ASP.NET MVC and jQuery
While working on the WeBlog project I realized that I needed a star rating system for blog posts.
March 2, 2010
by Michael Ceranski
· 32,751 Views
article thumbnail
Automatically Place a Semicolon at the End of Java Statements in Eclipse
we all know that java statements are terminated by a semicolon (;), but they’re a bit of a pain to add to the end of a line. one way would be to press end (to move to the end of the line) then press semicolon, but this is tedious. because this is something that you do often it’s worth learning how to do this faster. it’s a good thing eclipse can automatically put the semicolon at the end of the line, no matter where you are in the statement. it’s as easy as setting one preference and there’s a bonus preference for adding braces to the correct position as well. for something so small, it saves a lot of time. so in the example below, if you imagine that your cursor is placed after the word blue since you were editing the string. pressing semicolon will cause eclipse to place the semicolon after the closing bracket at the end. nice. system.out.println("the house is blue") how to set the semicolon preference the preference is disabled by default, so you have to enable it. go to window > preferences > java > typing . then enable semicolons under the section automatically insert at correct position . now when you press semicolon from anywhere in a statement, eclipse adds a semicolon to the end of the line and places the cursor right after the semicolon so you can start editing the next line. the preference should look like this: notes: sometimes you’d want to add a semicolon to a string literal instead of at the end of the line. eclipse caters for this by allowing you to press backspace after you pressed semicolon. pressing backspace will remove the semicolon from the end of the line, move your cursor to the original position in the string and add the semicolon to the string. if there’s already a semicolon at the end of the line, eclipse won’t try to add another to the end. it will just add the semicolon to wherever you placed it. eclipse is smart enough to know that for for loops you’d want to add the semicolon to the middle of the statement (eg. when editing the initialiser, condition and increment code). bonus tip: you can also add braces automatically at the correct position by selecting the braces option on the preference page. this comes in handy when your coding standards require braces to be on the same line as the control structure statement. for example, when adding a for or while loop, you can type { at any place in the first line and eclipse will insert it at the end of the line. from http://eclipseone.wordpress.com
March 2, 2010
by Byron M
· 15,167 Views · 13 Likes
article thumbnail
Sending Files With Sinatra
How to send files (attachments) with Sinatra 0.9.4. get '/some/:file' do |file| file = File.join('/some/path', file) send_file(file, :disposition => 'attachment', :filename => File.basename(file)) end I found the documentation was misleading in some cases and plain wrong in others. The key lie is the method "signature": def send_file(path, opts={}) This is confusing because Sinatra only uses options if you specify the disposition to either "inline" or "attachment". Otherwise, it simply throws the File (which doesn't know/care about your options). It is not enough to simply call send_file('/my/file') Although the documentation says File.basename will be uses as the default name, that simply isn't true. Using Firefox, I got "download" as the filename.
February 17, 2010
by Snippets Manager
· 4,522 Views
article thumbnail
Checkout Multiple Projects Automatically Into Your Eclipse Workspace With Team Project Sets
When working in Eclipse, you’ll often end up with a number of projects in your workspace that constitute an application. You could have a multi-tiered system with a web, server and database project and other miscellaneous ones. Or if you’re an Eclipse RCP developer, you could end up with dozens of plugins each represented by a project. Although multiple projects give you modularity (which is good), they can make it difficult to manage the workspace (which is bad). Developers have to check out each project individually from different locations in the repository. Sometimes they even have to get projects from multiple repositories. This is a painstakingly long and error-prone task. But an easier way to manage multiple projects is with Eclipse’s Team Project Sets (TPS). Creating a workspace becomes as easy as importing an XML file and waiting for Eclipse to do its job. Yes, there are other more sophisticated tools out there that do this and more (eg. Maven and Buckminster) but team project sets are a good enough start if you haven’t got anything set up and may be good enough for the longer term as well, depending on how your team works. Create a Team Project Set to share with other developers It’s easy to create a team project set (TPS). The first thing is to start with a workspace that already has all the projects checked out. Then it’s as easy as choosing File > Export > Team > Team Project Set, selecting the projects you want to export and then entering a file name. Done. But it’s always better to see it in action. In the video, I export 3 projects that I’ve already checked out from Subversion into a TPS file. Notes: You can select which projects should go into the TPS. This way you can exclude irrelevant or personal projects you’ve got in your workspace. Eclipse adds the extension .psf if you don’t provide one. The exported file is an XML file, with the default extension of psf, so in the video the file would be music.psf. There is a project entry for each project you exported that includes the project’s name and its repository location, separated by commas. Once created, the file is easy to edit so go ahead and make your own changes if you want to. Here is an example of what it looks like: svn/repo/music-application/trunk,music-application"/> svn/repo/music-db/trunk,music-db"/> svn/repo/music-web/trunk,music-web"/> Import the Team Project Set to checkout multiple projects into your workspace Now for the fun part. To import a team project set (TPS), start with any workspace (normally an empty one) and choose File > Import > Team > Team Project Set. Choose the TPS file that someone else kindly exported for you and then wait for Eclipse to do its magic. Notes: If you have an existing project in your workspace whose name matches a project in the TPS, Eclipse will prompt you whether you want to overwrite the project. I always choose No To All, since overwriting the project will mean you lose any changes you made to it. But if you have the urge to start from scratch then you can choose Yes. The import also creates a link to the repository in SVN Repositories, so you don’t have to do that. If one already exists, it will not duplicate it but reuse the existing connection. The process may take a while depending on the number of projects in the TPS and the speed of your repo checkouts. You can choose to run the import in the background (as I did in the video), giving you the opportunity to use Eclipse while the import happens. Otherwise, grab some coffee and wait for it to finish the checkouts. Gotcha: You may find that Eclipse 3.4 and lower may actually create a repository connection per project if the repository didn’t exist beforehand, which is not ideal. To solve this, create an initial repository root that’s shared by the projects and then do the import of the TPS. This problem has been fixed in 3.5 Managing the team project set and working with branches I’d recommend checking in the team project set into your repository and versioning/tagging it along with the rest of your code base. With each release you may be adding/removing projects and consequently updating the TPS, so it’s important that the TPS matches what the repo looks like at that point. As projects are added/removed with each release, you have 3 possibilities: Recreate the TPS from an existing workspace: Same as the steps above, but it means that whoever does the export needs to maintain an up to date workspace to reflect the current project structure. Modify an existing TPS with the new/deleted project: This entails adding/removing an entry from the PSF file. Not a lot of maintenance, but someone needs to remember to do this. Automatically create/update the TPS: You could write a script that somehow updates the TPS to reflect the new repo structure. For example, if you’re developing an Eclipse RCP application, the PDE Build provides a map file that could be used as input to create the PSF file. If you want to checkout a branch other than trunk, just open the PSF file and do a Find/Replace of trunk with your branch name. You could also introduce an automated process as part of your build/release scripts to update the TPS with the correct branch and check it back in automatically, but that’s really optional. From http://eclipseone.wordpress.com
February 13, 2010
by Byron M
· 22,841 Views
article thumbnail
How to Manage Keyboard Shortcuts in Eclipse and Why You Should
when i use eclipse i try and use shortcuts all the time. they really make me work faster and give me time to focus on getting the code out rather than slowing down to invoke ide commands with the mouse. because people work differently and on different things, it’s important to manage keyboard shortcuts to suit the way you work. so it’s good that eclipse makes it really easy to change shortcuts and also to view shortcuts for the commands you use a lot. i’ll discuss how to change keyboard shortcuts, how to avoid conflicts with existing ones, why it’s a good thing to manage shortcuts and then end off with some examples of common shortcuts that you should add to you arsenal. how do you manage keyboard shortcuts the main preference page can be found under window > preferences > general > keys (or faster: press ctrl+3 , type keys and press enter ). from here you can see all commands and assign/change their associated keyboard shortcuts. in the video, i’ll show you how to reassign a key. we’ll use this to assign ctrl+tab to switch to the next editor. notes: you don’t have to copy a command to assign/reassign a shortcut. i just prefer to keep the old shortcut in case someone else wants to take over my keyboard and expects the shortcut to work. all commands registered with eclipse are listed on the keys preference page. browse through them or search to see if your favourite command is listed. if it doesn’t have a shortcut assigned, then assign one immediately. the when dropdown on the dialog shows you in which context the command applies (eg. only when editing java source). you can assign the same shortcut to two different commands, but if the context differs eclipse will only execute the one command. i suggest you don’t change the context. notice that eclipse shows you which keys conflict with the selected one if their in the same context. but all the keys are already taken no, they’re not. firstly, if a key you like is already taken then be creative. use combos like ctrl+alt, alt+shift or even alt+shift+ctrl (easier to press then you think). these aren’t used as often as ctrl or ctrl+shift. you can sort by binding to see which keys are already used. secondly, eclipse allows you to assign a sequence of keystrokes to a command. eg. alt+shift+x, j (that’s used to run the current class as a java application) is invoked by pressing alt+shift+x, releasing the keys then pressing j. if you forgot your sequence shortcuts, just press the first part (eg. alt+shift+x), wait a second then eclipse helps you out by listing all commands that have this keystroke as the first part of the sequence. the list appears in the lower right corner of the window. this works for any commands assigned a sequence of keystrokes. here’s an example of what you might see when you press the first sequence of keystrokes (notice the list in the lower, right corner). tip: for custom commands you want to assign, use a well-known first keystroke to group your commands. for example, i use alt+shift+b (b for byron) as my grouping prefix. this way there are fewer conflicts with existing shortcuts and eclipse can show me a quick list if i forgot which keys i used. so why bother managing keyboard shortcuts managing keyboard shortcuts in eclipse is important because: not all eclipse commands have assigned shortcuts. a command you frequently use could be assigned a shortcut. eg. an svn commit is registered as an eclipse command but doesn’t have a keyboard shortcut assigned. assigning one yourself will speed up checking in changes. sometime eclipse gets it wrong. a good example is ctrl+f6 for switching editors – ctrl+tab is a much more sensible option since the keys are close together and doable with one hand. going through the list of shortcuts may give you ideas for working faster or even show you a command you didn’t know eclipse could do. but don’t shortcuts take a long time to learn? no ways! i often hear people complain that it takes too long to learn the shortcuts. i assure you that the 5 minutes it takes to learn the shortcut saves you hours, even days, of work over the months and years that you’ll be working on eclipse. here are some tips to get into and improve your keyboard usage: start by learning the shortcuts for the things you do often. are you using the mouse a lot to launch applications or select code? well, there’s a shortcut to launch apps and one to select code faster. keyboard shortcuts are often indicated next to menu items. note them and try to use them instead of reaching for the mouse. learn to punish yourself when you reach for the mouse by undoing your action and forcing yourself to use the keyboard. this seems counterproductive (and harsh) at first, but it forces your brain to rewire itself so you’ll favour the shortcuts instead of the mouse the next time. there is an eclipse plugin called mousefeed that shows you a keyboard alternative to a mouse click you performed. you can also configure it to cancel mouse clicks where a keyboard alternative is available, forcing you to use the keyboard in those instances. i don’t use it personally but what i’ve seen looks good. it’s definitely sounds like a good idea if you want to change your mousey ways and it relates nicely to my previous point. also keep this in mind: one of the easiest, surefire ways to work faster is to reduce the number of times you move your hands between the keyboard and mouse. the key is doing as much as possible with either one. for the mouse there are things like mouse gestures (if you’re on windows, try strokeit ). for the keyboard there are keyboard shortcuts and eclipse has hundreds of them ready to make your life easier (also see the excellent autohotkey for other ways to boost your keyboard usage). examples of useful keyboard shortcuts there are way too many shortcuts to list and you’ll come across the more useful ones in other tips . here are some you should get acquainted with at first and try to use all the time. shortcut action ctrl+1 quick fix list (for resolving errors/warnings) and also refactoring ctrl+space display the autocomplete list to select a relevant method/template, etc. ctrl+3 open quick access which allows you to run commands and navigate views and dialogs by searching for them, similar to launchy on windows or quicksilver on mac. ctrl+shift+r open any resource in the workspace, eg. xml file, class file, etc. ctrl+shift+t open a java type, eg. a class or interface. f3 go to the declaration of the method/class/variable f11/ctrl+f11 debug/run the last launched application (see this tip for more information) ctrl+alt+h display all methods that call a method (call hierarchy) f2 show javadoc for the current element (shift+f2 shows external javadoc) alt+up/down, alt+shift+down, ctrl+d move a line up/down, copy a line, delete a line (see this tip for more information) ctrl+/ comment/uncomment the current line or selected lines. you can be anywhere in the line, not necessarily at the beginning. you can press ctrl+shift+l to get a list of registered keyboard shortcuts in the lower right corner. but for a complete list, i prefer to go to the preference dialog as i can see all commands that are registered, even if they don’t have shortcuts registered from http://eclipseone.wordpress.com
February 12, 2010
by Byron M
· 36,441 Views
article thumbnail
Struts 2 Tutorial: Struts 2 Ajax Tutorial with Example
Welcome to the last part of 7 article series of Struts 2 Framework tutorials. In we saw how to implement File Upload functionality in Struts 2. In this article we will see how we can implement Ajax support in a webapplication using Struts2 framework. Struts 2 Tutorial List Part 7: Struts 2 Ajax Tutorial with Example AJAX support in Struts 2 Struts 2 provides built-in support to AJAX using Dojo Toolkit library. If you are new to Dojo, you may want to go through the Introduction of DOJO Toolkit. Struts 2 comes with powerful set of Dojo AJAX APIs which you can use to add Ajax support. In order to add Ajax support, you need to add following JAR file in your classpath: struts2-dojo-plugin.jar Also once we add this JAR file, we need to add following code snippet in whatever JSP file we need to add AJAX support. First define the taglib sx which we will use to add AJAX enabled tags. Add this head tag in your JSP between … tags. This sx:head tag will include required javascript and css files to implement Ajax. AJAX Example: Struts2 Ajax Drop Down Let us add simple AJAX support in our StrutsHelloWorld web application. We will use the base code that we used in previous articles and add Ajax on top of it. We will create a drop down which will Autocomplete and suggest the input. For this we will add Dojo support to our webapp. Step 1: Adding JAR file As discussed earlier we will add struts2-dojo-plugin.jar in classpath (WEB-INF/lib). Thus, following is the list of required jar files. Note that these jars are needed to run full application including all the samples of previous parts of this tutorial series. Step 2: Create AJAX Action class We will create an action class which will get called for our Ajax example. Create a file AjaxAutocomplete.java in net.viralpatel.struts2 package and copy following content into it. AjaxAutocomplete.java package net.viralpatel.struts2; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import com.opensymphony.xwork2.ActionSupport; public class AjaxAutocomplete extends ActionSupport { private String data = "Afghanistan, Zimbabwe, India, United States, Germany, China"; private List countries; private String country; public String execute() { countries = new ArrayList(); StringTokenizer st = new StringTokenizer(data, ","); while (st.hasMoreTokens()) { countries.add(st.nextToken().trim()); } return SUCCESS; } public String getCountry() { return this.country; } public List getCountries() { return countries; } public void setCountries(List countries) { this.countries = countries; } public void setCountry(String country) { this.country = country; } } In above code we have created a simple action class with attribute String country and List countries. The countries list will be populated with country names when execute() method is called. Here for this example, we have loaded static data. You may feel free to change this and add data from database. Step 3: Create JSP Create JSP file to display Autocomplete textbox for our Ajax action. Create AjaxDemo.jsp in WebContent directory. AjaxDemo.jsp Struts 2 Autocomplete (Drop down) Example! Country: In above JSP file we have used sx:autocompleter tag to render an autocomplete drop down which users Ajax class to fetch data internally. Note that we have mapped the list attribute with List countries. Step 4: Creating Struts.xml entry Add following action entry in Struts.xml file: /ajaxdemo.tiles /ajaxdemo.tiles Notice that we are using Tiles here in this example. You may want to use AjaxDemo.jsp instead of /ajaxdemo.tiles to render the output directly in JSP. That’s All Folks Compile and Run the application in eclipse. Download Source Code Click here to download Source Code without JAR files (24KB) Conclusion Struts2 Framework provides wide variety of features to create a rich web application. In this Struts2 series we saw different aspects of Struts 2 like introduction of struts2, hello world application, validation framework, tiles plugin, strurts2 interceptors, file upload and ajax support.
January 20, 2010
by Viral Patel
· 124,839 Views
article thumbnail
Struts 2 Tutorial: Create Struts 2 Application in Eclipse
Welcome to the Part 2 of 7-part series where we will explore the world of Struts 2 Framework. In we went through the basics of Struts2, its Architecture diagram, the request processing lifecycle and a brief comparison of Struts1 and Struts2. If you have not gone through the previous article, I highly recommend you to do that before starting hands-on today. Struts 2 Tutorial List Part 7: Struts 2 Ajax Tutorial with Example Related: Create Struts Application with Eclipse Things We Need Before we starts with our first Hello World Struts 2 Example, we will need few tools. JDK 1.5 above (download) Tomcat 5.x above or any other container (Glassfish, JBoss, Websphere, Weblogic etc) (download) Eclipse 3.2.x above (download) Apache Struts2 JAR files:(download). Following are the list of JAR files required for this application. commons-logging-1.0.4.jar freemarker-2.3.8.jar ognl-2.6.11.jar struts2-core-2.0.12.jar xwork-2.0.6.jar Note that depending on the current version of Struts2, the version number of above jar files may change. Our Goal Our goal is to create a basic Struts2 application with a Login page. User will enter login credential and if authenticated successfully she will be redirected to a Welcome page which will display message ”Howdy, …!“. If user is not authenticated, she will be redirected back to the login page. Getting Started Let us start with our first Struts2 based application. Open Eclipse and goto File -> New -> Project and select Dynamic Web Project in the New Project wizard screen. After selecting Dynamic Web Project, press Next. Write the name of the project. For example StrutsHelloWorld. Once this is done, select the target runtime environment (e.g. Apache Tomcat v6.0). This is to run the project inside Eclipse environment. After this press Finish. Once the project is created, you can see its structure in Project Explorer. Now copy all the required JAR files in WebContent -> WEB-INF -> lib folder. Create this folder if it does not exists. Mapping Struts2 in WEB.xml As discussed in the previous article (Introduction to Struts2), the entry point of Struts2 application will be the Filter define in deployment descriptor (web.xml). Hence we will define an entry of org.apache.struts2.dispatcher.FilterDispatcher class in web.xml. Open web.xml file which is under WEB-INF folder and copy paste following code. Struts2 Applicationstruts2org.apache.struts2.dispatcher.FilterDispatcherstruts2/*Login.jsp The above code in web.xml will map Struts2 filter with url /*. The default url mapping for struts2 application will be /*.action. Also note that we have define Login.jsp as welcome file. The Action Class We will need an Action class that will authenticate our user and holds the value for username and password. For this we will create a package net.viralpatel.struts2 in the source folder. This package will contain the action file. Create a class called LoginAction in net.viralpatel.struts2 package with following content. package net.viralpatel.struts2;public class LoginAction {private String username;private String password;public String execute() {if (this.username.equals("admin")&& this.password.equals("admin123")) {return "success";} else {return "error";}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;} Note that, above action class contains two fields, username and password which will hold the values from form and also contains an execute() method that will authenticate the user. In this simple example, we are checking if username is admin and password is admin123. Also note that unlike Action class in Struts1, Struts2 action class is a simple POJO class with required attributes and method. The execute() method returns a String value which will determine the result page. Also, in Struts2 the name of the method is not fixed. In this example we have define method execute(). You may want to define a method authenticate() instead. The ResourceBundle ResourceBundle is very useful Java entity that helps in putting the static content away from the source file. Most of the application define a resource bundle file such as ApplicationResources.properties file which contains static messages such as Username or Password and include this with the application. ResourceBundle comes handy when we want to add Internationalization (I18N) support to an application. We will define an ApplicationResources.properties file for our application. This property file should be present in WEB-INF/classes folders when the source is compiled. Thus we will create a source folder called resources and put the ApplicationResources.properties file in it. To create a source folder, right click on your project in Project Explorer and select New -> Source Folder. Specify folder name resources and press Finish. Create a file ApplicationResources.properties under resources folder. Copy following content in ApplicationResources.properties. label.username= Usernamelabel.password= Passwordlabel.login= Login The JSP We will create two JSP files to render the output to user. Login.jsp will be the starting point of our application which will contain a simple login form with username and password. On successful authentication, user will be redirected to Welcome.jsp which will display a simple welcome message. Create two JSP files Login.jsp and Welcome.jsp in WebContent folder of your project. Copy following content into it. Login.jsp Struts 2 - Login Application Welcome.jsp Howdy, ...! Note that we have used struts2 tag to render the textboxes and labels. Struts2 comes with a powerful built-in tag library to render UI elements more efficiently. The struts.xml file Struts2 reads the configuration and class definition from an xml file called struts.xml. This file is loaded from the classpath of the project. We will define struts.xml file in the resources folder. Create file struts.xml in resources folder. Copy following content into struts.xml. Welcome.jspLogin.jsp Note that in above configuration file, we have defined Login action of our application. Two result paths are mapped with LoginAction depending on the outcome of execute() method. If execute() method returns success, user will be redirected to Welcome.jsp else to Login.jsp. Also note that a constant is specified with name struts.custom.i18n.resources. This constant specify the resource bundle file that we created in above steps. We just have to specify name of resource bundle file without extension (ApplicationResources without .properties). Our LoginAction contains the method execute() which is the default method getting called by Sturts2. If the name of method is different, e.g. authenticate(); then we should specify the method name in tag. Almost Done We are almost done with the application. You may want to run the application now and see the result yourself. I assume you have already configured Tomcat in eclipse. All you need to do: Open Server view from Windows -> Show View -> Server. Right click in this view and select New -> Server and add your server details. To run the project, right click on Project name from Project Explorer and select Run as -> Run on Server (Shortcut: Alt+Shift+X, R) But there is one small problem. Our application runs perfectly fine at this point. But when user enters wrong credential, she is redirected to Login page. But no error message is displayed. User does not know what just happened. A good application always show proper error messages to user. So we must display an error message Invalid Username/Password. Please try again when user authentication is failed. Final Touch To add this functionality first we will add the error message in our ResourceBundle file. Open ApplicationResources.properties and add an entry for error.login in it. The final ApplicationResources.properties will look like: label.username= Usernamelabel.password= Passwordlabel.login= Loginerror.login= Invalid Username/Password. Please try again. Also we need to add logic in LoginAction to add error message if user is not authenticated. But there is one problem. Our error message is specified in ApplicationResources.properties file. We must specify key error.login in LoginAction and the message should be displayed on JSP page. For this we must implement com.opensymphony.xwork2.TextProvider interface which provides method getText(). This method returns String value from resource bundle file. We just have to pass the key value as argument to getText() method. The TextProvider interface defines several method that we must implement in order to get hold on getText() method. But we don’t want to spoil our code by adding all those methods which we do not intend to use. There is a good way of dealing with this problem. Struts2 comes with a very useful class com.opensymphony.xwork2.ActionSupport. We just have to extend our LoginAction class with this class and directly use methods such as getText(), addActionErrors() etc. Thus we will extend the LoginAction class with ActionSupport class and add the logic for error reporting into it. The final code in LoginAction must look like: package net.viralpatel.struts2;import com.opensymphony.xwork2.ActionSupport;public class LoginAction extends ActionSupport {private String username;private String password;public String execute() {if (this.username.equals("admin")&& this.password.equals("admin123")) {return "success";} else {addActionError(getText("error.login"));return "error";}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;} And that’s it. Our first Hello World Struts2 Application is now ready. That’s All Folks Execute the application in Eclipse and run it in your favorite browser. Login page Welcome page Login page with error Download Source Code Click here to download Source Code without JAR files (9KB). Moving On Now that we have created our first webapp using Struts2 framework, we know how the request flows in Struts2. We also know the use of struts.xml and properties file. In this application we implemented a preliminary form of validation. In we will learn more about Validation Framework in Struts2 and implement it in our example. Original article: http://viralpatel.net/blogs/2009/12/tutorial-create-struts-2-application-eclipse-example.html
January 15, 2010
by Viral Patel
· 289,765 Views
article thumbnail
How to Create a Scheduler Module in a Java EE 6 Application with TimerService
Many a time, in a Java EE application, besides the user-triggered transactions via the UI (e.g. from the JSF), there's a need for a mechanism to execute long running jobs triggered over time, e.g., batch jobs. Although in the EJB specs there's a Timer service, where Session Beans can be scheduled to run at intervals through annotations as well as programmatically, the schedule and intervals to execute the jobs have to be pre-determined during development time and Glassfish does not provide the framework and the means to do that out-of-the-box. So it is left to the developer to code that functionality or to choose a 3rd party product to do that. In one of my previous projects using a different application server, I implemented a scheduler module for the application. So with that experience, I will discuss in this article how to create a simple scheduler called SchedulerApp in NetBeans IDE 6.8 that can be deployed in Glassfish v3. The example comes with a framework and the JSF2 PrimeFaces-based UI to schedule and manage (CRUD) your batch jobs implemented by Stateless Session Beans without having to pre-determine the time and interval to execute them during development time. Below is the Class Diagram to give you an overview of the application: Through this exercise, I also hope that you will have a better understanding of the Timer Service in the EJB specs and how you can use it in your projects. Note: If you cannot get your copy running, not to worry, you can get a working copy here. Tutorial Requirements Before we proceed, make sure you review the requirements in this section. Prerequisites This tutorial assumes that you have some basic knowledge of, or programming experience with, the following technologies. JavaServer Faces (JSF) with Facelets Enterprise Java Beans (EJB) 3/3.1 esp. the Timer Service Basic knowledge of using NetBeans IDE will help to reduce the time required to do this tutorial Software needed for this Tutorial Before you begin, you need to download and install the following software on your computer: NetBeans IDE 6.8 (Java pack), http://www.netbeans.org Glassfish Enterprise Server v3, https://glassfish.dev.java.net PrimeFaces Component Library, http://www.primefaces.org Notes: The Glassfish Enterprise Server is included in the Java pack of NetBeans IDE, however, Glassfish can be installed separately from the IDE and added later into Servers services in the IDE. A copy of the working solution is included here if needed. Creating the Enterprise Projects The approach for developing the demo app, SchedulerApp, will be from the back end, i.e., the artifacts and services needed by the front-end UI will be created first, then working forward to the User Interface, i.e., the Ajax-based Web UI will be done last. The first step in creating the application is to create the necessary projects in NetBeans IDE. Choose "File > New Project" to open the New Project Wizard. Under Categories, select Java EE; under Projects select Enterprise Application. Click Next. Select the project location and name the project, SchedulerApp, and click Next. Select the installed Glassfish v3 as the server, and Java EE 6 as the Java EE Version, and click Finish. The above steps will create 3 projects, namely SchedulerApp (Enterprise Application project), SchedulerApp-ejb (EJB project), and SchedulerApp-war (Web project). Creating the Session Beans Before creating the necessary session bean classes, let's look at one of the main classes, JobInfo, which will be heavily used in the application both at the front-end and back. Basically this is a Value Object class that stores information required to configure the timer. Below is an abstract of the class: package com.schedulerapp.common; public class JobInfo implements java.io.Serializable { private static SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy"); private static SimpleDateFormat sdf2 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); private String jobId; private String jobName; private String jobClassName; private String description; //Details required by the SchedulerExpression private Date startDate; private Date endDate; private String second; private String minute; private String hour; private String dayOfWeek; private String dayOfMonth; private String month; private String year; private Date nextTimeout; public JobInfo() { this("", "", "java:module/"); } public JobInfo(String jobId, String jobName, String jobClassName) { this.jobId = jobId; this.jobName = jobName; this.jobClassName = jobClassName; this.description = ""; //Default values, everyday midnight this.startDate = new Date(); this.endDate = null; this.second = "0"; this.minute = "0"; this.hour = "0"; this.dayOfMonth = "*"; //Every Day this.month = "*"; //Every Month this.year = "*"; //Every Year this.dayOfWeek = "*"; //Every Day of Week (Sun-Sat) } //Getter and Setter methods for the above attributes... /* * Expression of the schedule set in the object */ public String getExpression() { return "sec=" + second + ";min=" + minute + ";hour=" + hour + ";dayOfMonth=" + dayOfMonth + ";month=" + month + ";year=" + year + ";dayOfWeek=" + dayOfWeek; } @Override public boolean equals(Object anotherObj) { if (anotherObj instanceof JobInfo) { return jobId.equals(((JobInfo) anotherObj).jobId); } return false; } @Override public String toString() { return jobId + "-" + jobName + "-" + jobClassName; } } Notice the class holds the information about the job and its schedule. Create the above class in the EJB project, SchedulerApp-ejb with the package name, com.schedulerapp.common. After creating this class, we are ready to create the session beans. Creating the BatchJob Session Beans In this demo, we will be creating THREE batch jobs, namely: BatchJobA, BatchJobB and BatchJobC, where each is a Stateless Session Bean that implements a Local Interface, BatchJobInterface. The Interface will have a method, executeJob(javax.ejb.Timer timer), so each of the batch job session bean will need to implement it and this becomes the starting point for the batch jobs. Let's proceed to create them and you will see what I mean. In the Projects window, right-click on the SchedulerApp-ejb project and select "New > Session Bean..." In the New Session Bean dialog, specify the EJB Name as BatchJobA, the package as "com.schedulerapp.batchjob", Session Type as Stateless and select Local for Create Interface option Notice 2 files are created: BatchJobA (Implementation class) and BatchJobALocal (Local Interface). Here I want to rename the Interface so that it has a generic name like BatchJobInterface In the project view, navigate to the BatchJobALocal file. Right-click on the item and select "Refactor > Rename...", and change the name to BatchJobInterface. Open the renamed file, BatchJobInterface in the editor, and add the method: @Local public interface BatchJobInterface { public void executeJob(javax.ejb.Timer timer); } Notice the file, BatchJobA becomes errorneous after the above is performed. Open the file, BatchJobA and you should see the error hint (lightbulb with exclamation icon) on the left side of the editor. Click on the icon and select "Implement all abstract methods" and edit the file so that it looks like this: @Stateless public class BatchJobA implements BatchJobInterface { static Logger logger = Logger.getLogger("BatchJobA"); @Asynchronous public void executeJob(Timer timer) { logger.info("Start of BatchJobA at " + new Date() + "..."); JobInfo jobInfo = (JobInfo) timer.getInfo(); try { logger.info("Running job: " + jobInfo); Thread.sleep(30000); //Sleep for 30 seconds } catch (InterruptedException ex) { } logger.info("End of BatchJobA at " + new Date()); } } As you can see, the executeJob method does nothing but just sleeps for 30 sec to simulate a long running job. And because of that, it is made an asynchronous method thru the @Asynchronous annotation so that it doesn't block the calling Session Bean. Notice also that the JobInfo object is extracted from the Timer object so that you have the information to execute your job. We will see later how the JobInfo object got into the Timer object. We will next create the other 2 batch job session beans: BatchJobA and BatchJobB using the Copy/Paste and Refactor features of NB6.8. In the project view, navigate to the file, BatchJobA. Right-click on the item and select "Copy" In the same view, right-click the package, "com.schedulerapp.batchjob" and select "Paste > Refactor Copy..." In the Copy Class dialog, enter "BatchJobB" for the New Name field and click on the Refactor button. Notice the new Session Bean, BatchJobB is created with a few easy clicks of a button. The only thing to change in the new class is the print statements, where "BatchJobA" will be changed to "BatchJobB". Repeat the above steps to create BatchJobC session bean. So we now have THREE batch job session beans: BatchJobA, BatchJobB and BatchJobC that implements the Local Interface, BatchJobInterface. We will next create the last Session Bean for this project. Creating the Job Session Bean Here, we will create the Job Session Bean whose main responsibility is to provide the necessary services to the front-end UI to manage (CRUD) the jobs and also provide the timeout method for the TimerService. In the Projects window, right-click on the SchedulerApp-ejb project and select "New > Session Bean..." In the New Session Bean dialog, specify the EJB Name as JobSessionBean, the package as "com.schedulerapp.ejb", Session Type as Stateless and leave Create Interface unchecked, i.e. no Interface (New in EJB 3.1), and click Finish. Open the newly created file, JobSessionBean in the editor and edit the content so that it looks like the following: @Stateless @LocalBean public class JobSessionBean { @Resource TimerService timerService; //Resource Injection static Logger logger = Logger.getLogger("JobSessionBean"); /* * Callback method for the timers. Calls the corresponding Batch Job Session Bean based on the JobInfo * bounded to the timer */ @Timeout public void timeout(Timer timer) { System.out.println("###Timer <" + timer.getInfo() + "> timeout at " + new Date()); try { JobInfo jobInfo = (JobInfo) timer.getInfo(); BatchJobInterface batchJob = (BatchJobInterface) InitialContext.doLookup( jobInfo.getJobClassName()); batchJob.executeJob(timer); //Asynchronous method } catch (NamingException ex) { logger.log(Level.SEVERE, null, ex); } catch (Exception ex1) { logger.severe("Exception caught: " + ex1); } } /* * Returns the Timer object based on the given JobInfo */ private Timer getTimer(JobInfo jobInfo) { Collection timers = timerService.getTimers(); for (Timer t : timers) { if (jobInfo.equals((JobInfo) t.getInfo())) { return t; } } return null; } /* * Creates a timer based on the information in the JobInfo */ public JobInfo createJob(JobInfo jobInfo) throws Exception { //Check for duplicates if (getTimer(jobInfo) != null) { throw new DuplicateKeyException("Job with the ID already exist!"); } TimerConfig timerAConf = new TimerConfig(jobInfo, true); ScheduleExpression schedExp = new ScheduleExpression(); schedExp.start(jobInfo.getStartDate()); schedExp.end(jobInfo.getEndDate()); schedExp.second(jobInfo.getSecond()); schedExp.minute(jobInfo.getMinute()); schedExp.hour(jobInfo.getHour()); schedExp.dayOfMonth(jobInfo.getDayOfMonth()); schedExp.month(jobInfo.getMonth()); schedExp.year(jobInfo.getYear()); schedExp.dayOfWeek(jobInfo.getDayOfWeek()); logger.info("### Scheduler expr: " + schedExp.toString()); Timer newTimer = timerService.createCalendarTimer(schedExp, timerAConf); logger.info("New timer created: " + newTimer.getInfo()); jobInfo.setNextTimeout(newTimer.getNextTimeout()); return jobInfo; } /* * Returns a list of JobInfo for the active timers */ public List getJobList() { logger.info("getJobList() called!!!"); ArrayList jobList = new ArrayList(); Collection timers = timerService.getTimers(); for (Timer t : timers) { JobInfo jobInfo = (JobInfo) t.getInfo(); jobInfo.setNextTimeout(t.getNextTimeout()); jobList.add(jobInfo); } return jobList; } /* * Returns the updated JobInfo from the timer */ public JobInfo getJobInfo(JobInfo jobInfo) { Timer t = getTimer(jobInfo); if (t != null) { JobInfo j = (JobInfo) t.getInfo(); j.setNextTimeout(t.getNextTimeout()); return j; } return null; } /* * Updates a timer with the given JobInfo */ public JobInfo updateJob(JobInfo jobInfo) throws Exception { Timer t = getTimer(jobInfo); if (t != null) { logger.info("Removing timer: " + t.getInfo()); t.cancel(); return createJob(jobInfo); } return null; } /* * Remove a timer with the given JobInfo */ public void deleteJob(JobInfo jobInfo) { Timer t = getTimer(jobInfo); if (t != null) { t.cancel(); } } } Take note of the followings in the above code: Timer Service is made available thru Resource Injection near the top of the class The callback method for the timers created is timeout thru the use of the @Timeout annotation Notice how the JobInfo object gets into the timer thru the TimerConfig object in the createJob method Notice how the Batch Job session beans are being lookup and accessed in the timeout method. The job class name will be the Portable JNDI name provided by the user in the UI later At this point, we are done with the EJB project, and will now move on to the Web project. Creating the Web UI using JSF 2.0 with PrimeFaces At the time of writing this tutorial, there are not many choices of Ajax-based frameworks that works with JSF 2.0 as it is still quite new. But I have found PrimeFaces to be the most complete and suitable for this demo as it has implemented the dataTable UI component and it seems to be the easiest to integrate into the NetBeans IDE. Preparing the Web project to use JSF 2.0 and PrimeFaces Before creating the web pages, ensure the JavaServer Faces framework is added to the Web project, SchedulerApp-war. In the Project view, right-click on the Web project, SchedulerApp-war, and select Properties (last item). Under the Categories items, select Frameworks, and ensure the JavaServer Faces is added to the Used Frameworks list: Before we are able to use PrimeFaces components in our facelets, we need to include its library in NetBeans IDE and set up a few things. Download the PrimeFaces library (primefaces-2.0.0.RC.jar) from http://www.primefaces.org/downloads.html [13] and store it somewhere on the local disk. To allow future projects to use PrimeFaces, I chose to create a Global library in NetBeans for PrimeFaces. Select "Tools > Libraries" from the NetBeans IDE main menu. In the Library Manager dialog, choose "New Library" and provide a name for the library, e.g. "PrimeFaces2". With the new "PrimeFaces2" library selected, click on the "Add JAR/Folder..." button and select the jar file that was downloaded earlier and click OK to complete: Next, we need to add the newly created library, PrimeFaces2 to the Web project: Select the Web project, SchedulerApp-war, from the Project window, right-click and select "Properties". Under the Libraries category, click on the "Add Library..." button (on the right), and choose the PrimeFaces2 library and click OK to complete: Because we will be using Facelets in our demo, we will update the XHTML template in NetBeans so that all the XHTML files created subsequently will already have the required namespaces and resources needed for the development. Choose "Tools > Templates" from the NetBeans menu. In the Template Manager dialog, select "Web > XHTML" and click the "Open in Editor" button. Edit the content of the file so that it looks like this: <#assign licenseFirst = ""> <#include "../Licenses/license-${project.license}.txt"> TODO write content Lastly, we need to add the following statements in the web.xml file of the Web project for the PrimeFaces components to work properly: Faces Servlet /faces/* *.jsf Resource Servlet org.primefaces.resource.ResourceServlet Resource Servlet /primefaces_resource/* com.sun.faces.allowTextChildren true At this point, we are done setting up and configuring the environment for PrimeFaces to work in NetBeans. In the sections below, we will create the JSF pages to present the screens to perform the CRUD functions. To achieve this, we will be creating THREE web pages: JobList - listing of all the active Jobs/Timers created in a tabular form JobDetails - view/update/delete the selected Job JobNew - create a new Job Creating the Backing Beans for the JSF pages Before creating the actual JSF pages, we first need to create the backing beans that provides the properties and action handlers for the JSF pages (XHTML). Here we will create TWO backing beans: JobList - RequestScoped backing bean for the Job Listing page JobMBean - SessionScoped backing bean for the rest of the JSF pages Steps to create the beans: In the Project view, right-click on the Web project, SchedulerApp-war, and select "New > JSF Managed Bean...", specify JobList as the Class Name, "com.schedulerapp.web" as the Package Name, and the scope to be request Repeat the steps to create the second backing bean, name it JobMBean and set the scope to be session instead. Edit the class, JobList, so that it looks like this: @ManagedBean(name = "JobList") @RequestScoped public class JobList implements java.io.Serializable { @EJB private JobSessionBean jobSessionBean; private List jobList = null; /** Creates a new instance of JobList */ public JobList() { } @PostConstruct public void initialize() { jobList = jobSessionBean.getJobList(); } /* * Returns a list of active Jobs/Timers */ public List getJobs() { return jobList; } } Edit the class, JobMBean, so that it looks like this: @ManagedBean(name = "JobMBean") @SessionScoped public class JobMBean implements java.io.Serializable { @EJB private JobSessionBean jobSessionBean; private JobInfo selectedJob; private JobInfo newJob; /** Creates a new instance of JobMBean */ public JobMBean() { } /* * Getter method for the newJob property */ public JobInfo getNewJob() { return newJob; } /* * Setter method for the newJob property */ public void setNewJob(JobInfo newJob) { this.newJob = newJob; } /* * Getter method for the selectedJob property */ public JobInfo getSelectedJob() { return selectedJob; } /* * Setter method for the selectedJob property */ public String setSelectedJob(JobInfo selectedJob) { this.selectedJob = jobSessionBean.getJobInfo(selectedJob); return "JobDetails"; } /* * Action handler for back to Listing Page */ public String gotoListing() { return "JobList"; } /* * Action handler for New Job button */ public String gotoNew() { System.out.println("gotoNew() called!!!"); newJob = new JobInfo(); return "JobNew"; } /* * Action handler for Duplicate button in the Details page */ public String duplicateJob() { newJob = selectedJob; newJob.setJobId(""); return "JobNew"; } /* * Action handler for Update button in the Details page */ public String updateJob() { FacesContext context = FacesContext.getCurrentInstance(); try { selectedJob = jobSessionBean.updateJob(selectedJob); context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success", "Job successfully updated!")); } catch (Exception ex) { Logger.getLogger(JobMBean.class.getName()).log(Level.SEVERE, null, ex); context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Failed", ex.getCause().getMessage())); } return null; } /* * Action handler for Delete button in the Details page */ public String deleteJob() { jobSessionBean.deleteJob(selectedJob); return "JobList"; } /* * Action handler for Create button in the New page */ public String createJob() { FacesContext context = FacesContext.getCurrentInstance(); try { selectedJob = jobSessionBean.createJob(newJob); context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Sucess", "Job successfully created!")); return "JobDetails"; } catch (Exception ex) { Logger.getLogger(JobMBean.class.getName()).log(Level.SEVERE, null, ex); context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Failed", ex.getCause().getMessage())); } return null; } } Now, we have all the services and properties ready to be used by the JSF pages. Creating the JSF pages Finally, we are ready to create the THREE JSF pages: JobList, JobDetails and JobNew. In the Project view, right-click on the Web project, SchedulerApp-war, and select "New > XHTML...", specify JobList as the File Name. Note: If the item "XHTML..." doesn't appear in your menu list, select "New > Others..." instead, then in the New File dialog, select Web under Categories and you should be able to see the XHTML file type on the right. Repeat the above step for JobDetails and JobNew. Edit the file, JobList.xhtml to look like this: Job List Edit the file, JobDetails.xhtml to look like this: Help Edit the file, JobNew.xhtml to look like this: Help At this point, we are done with all the coding, and it's now time to verify the results. Perform a "Clean and Build" of the project and deploy it to the Glassfish v3 server. Testing the application Here, we will do a simple test to verify that the application is working. We will schedule 3 jobs as follows: Job 1 - run BatchJobA every 2 minutes (just to make sure we see the job running) Job 2 - run BatchJobB everyday at 11pm Job 3 - run BatchJobC every Sunday at 1am Steps to create the jobs: Go to the listing page, http://localhost:8080/SchedulerApp-war/JobList.jsf and you should see the following screen: Click on the "New Job" button below the table. Enter the details for Job 1 as follows and click on the "Create" button Click on the "Duplicate" button below to create a new Job using the current information. Enter the details for Job 2 as follows and click on the "Create" button Click on the "Duplicate" button below to create a new Job using the current information. Enter the details for Job 3 as follows and click on the "Create" button At this point, we are done creating the jobs, click on the "Back" button to see the listing. The Job List page should consists of 3 jobs that was created in the above steps Things to Note The Portable JNDI syntax for accessing the Session Beans: BatchJobA, BatchJobB and BatchJobC The "*" in the text fields represents "Every", see Java EE 6 Tutorial for details You should be able see in the log file, server.log, that BatchJobA now runs every 2 minutes The timers(jobs) are persistent, i.e. they will survive server restarts. Try restarting ther server and view the Job list again Try out the other functions of the CRUD and schedule your own jobs to see it in action. Summary Congratulations! You now have a simple scheduler to schedule your long running jobs in your application. With this framework and the GUI, you can have the flexibility and full control over the jobs you want to manage without having to pre-determine the time and interval to run them during Design and Development phase. Although the timers are persistent, the server may remove them when changes, such as new deployments, are detected. As such, you can further extend the scheduler to persist information in the database in a more dynamic and complex environment, e.g., a cluster. Good luck and have fun using the Scheduler. If you cannot get your copy running, not to worry, you can get a working copy here. See Also For other related resources, see the following: Develop Java EE 5 application with Visual JSF, EJB3 and JPA Securing Java EE 6 application with JEE Security and LDAP How to Create a Java EE 6 Application with JSF 2, EJB 3.1, JPA, and NetBeans IDE 6.8
January 10, 2010
by Christopher Lam
· 109,661 Views · 1 Like
article thumbnail
Spring Integration and Apache Camel
Spring Integration and Apache Camel are open source frameworks providing a simpler solution for the Integration problems in the enterprise, to quote from their respective websites: Apache Camel - Apache Camel is a powerful open source integration framework based on known Enterprise Integration Patterns with powerful Bean Integration. Spring Integration - It provides an extension of the Spring programming model to support the well-known Enterprise Integration Patterns while building on the Spring Framework's existing support for enterprise integration. Essentially Spring Integration and Apache Camel enable applications to integrate with other systems. This article seeks to provide an implementation for an integration problem using both Spring Integration and Apache Camel. The objective is to show how easy it is to use these frameworks for a fairly complicated integration problem and to recommend either of these great products for your next Integration challenge. Problem: To illustrate the use of these frameworks consider a simple integration scenario, described using EIP terminology: The application needs to get a "Report" by aggregating "Sections" from a Section XML over http service. Each request for Report consists of a set of request for sections – in this specific example there are requests for three sections, the header, body and footer. The XML over http service returns a Section for the Section Request. The responses need to be aggregated into a single report. A sample test for this scenario is of the following type: ReportGenerator reportGenerator = reportGeneratorFactory.createReportGenerator(); List sectionRequests = new ArrayList(); String entityId="A Company"; sectionRequests.add(new SectionRequest(entityId,"header")); sectionRequests.add(new SectionRequest(entityId,"body")); sectionRequests.add(new SectionRequest(entityId,"footer")); ReportRequest reportRequest = new ReportRequest(sectionRequests); Report report = reportGenerator.generateReport(reportRequest); List sectionOfReport = report.getSections(); System.out.println(report); assertEquals(3, sectionOfReport.size()); The “ReportGenerator” is the messaging gateway, hiding the details of the underlying messaging infrastructure and in this specific case also the integration API – Apache Camel or Spring Integration. To start with, let us implement a solution to this integration problem using Spring Integration as the Framework, followed by Apache Camel. The complete working code using Spring Integration and Apache Camel is also available with the article. Solution Using Spring Integration: The Gateway component is easily configured using the following entry in the Spring Configuration. Internally Spring Integration uses AOP to hook up a component which routes the requests from an internal input channel and waits for the response in the response channel. The component to Split the Input Report Request to Section Request is fairly straightforward: public class SectionRequestSplitter { public List split(ReportRequest reportRequest){ return reportRequest.getSectionRequests(); } } and to hook this splitter with Spring Integration: Next, to transform the Section Request to an XML format - The component is the following: public class SectionRequestToXMLTransformer { public String transform(SectionRequest sectionRequest){ //this needs to be optimized...purely for demonstration of the concept String sectionRequestAsString = "" + sectionRequest.getEntityId() + "" + sectionRequest.getSectionId() + ""; return sectionRequestAsString; } } and is hooked up in the Spring Integration configuration file in the following way: To send an XML over http request using the Section Request XML to a section Service: To transform the Section Response XML to a Section Object - The component is the following: public class SectionResponseXMLToSectionTransformer { public Section transform(String sectionXML) { SAXReader saxReader = new SAXReader(); Document document; String sectionName = ""; String entityId = ""; try { document = saxReader.read(new StringReader(sectionXML)); sectionName = document .selectSingleNode("/section/meta/sectionName").getText(); entityId = document.selectSingleNode("/section/meta/entityId") .getText(); } catch (DocumentException e) { e.printStackTrace(); } return new Section(entityId, sectionName, sectionXML); } } and is hooked up in the Spring Integration configuration file in the following way: To aggregate the Sections together into a report, the component is the following:: public class SectionResponseAggregator { public Report aggregate(List sections) { return new Report(sections); } } and is hooked up in the Spring Integration configuration file in the following way: This completes the Spring Integration implementation for this Integration Problem. The following is the complete Spring Integration configuration file: A working sample is provided with the article(Download, extract and run "mvn test") Solution using Apache Camel: Apache Camel allows the route to be defined using multiple DSL implementations – Java DSL, Scala DSL and an XML based DSL. The recommended approach is to use Spring CamelContext as a runtime and the Java DSL for route development. The following is to build the Spring Camel Context: The route is configured by the Java based DSL: public class CamelRouteBuilder extends RouteBuilder { private String serviceURL; @Override public void configure() throws Exception { from("direct:start") .split().method("sectionRequestSplitterBean", "split") .aggregationStrategy(new ReportAggregationStrategy()) .transform().method("sectionRequestToXMLBean", "transform") .to(serviceURL) .transform().method("sectionResponseXMLToSectionBean", "transform"); } public void setServiceURL(String serviceURL) { this.serviceURL = serviceURL; } } Apache Camel does not provide an out of the box Message Gateway feature, however it is fairly easy to create a wrapper component that can hide the underlying details in the following way: Reader davsclaus has provided references to two mechanisms with Apache Camel to provide an out of the box Messaging Gateway - Messaging Gateway EIP and Camel Proxy which allows a POJO to be used as a Mesaging Gateway. Camel Proxy will be used with the article, and can be configured in the Camel Configuration files in the following way: Per davsclaus, there is a bug in Apache Camel(2.1 or older) when invoking a bean later in the route(the splitter bean), which is to be fixed in Apache Camel 2.2. To work around this bug, a convertBody step will be introduced in the route: from("direct:start") .convertBodyTo(ReportRequest.class) .split(bean("sectionRequestSplitterBean", "split"), new ReportAggregationStrategy()) .transform().method("sectionRequestToXMLBean", "transform") .to(serviceURL) .transform().method("sectionResponseXMLToSectionBean", "transform"); The component to Split the Input Report Request to Section Request is exactly same as Spring Integration component: public class SectionRequestSplitter { public List split(ReportRequest reportRequest){ return reportRequest.getSectionRequests(); } } To hook the component with Apache Camel: from("direct:start") .split().method("sectionRequestSplitterBean", "split") .... Next to transform the Section Request to an XML format, again this is exactly same as the implementation for Spring Integration, with hook being provided in the following manner: ...... .transform().method("sectionRequestToXMLBean", "transform") ...... To send an XML over http request using the Section Request XML to a section Service: ...... .transform().method("sectionRequestToXMLBean", "transform") .to(serviceURL) ......... To transform the Section Response XML to a Section object, the component is exactly same as the one used with Spring Integration, with the following highlighted hook in the Camel route: ...... .transform().method("sectionResponseXMLToSectionBean", "transform"); To aggregate the Section responses together into a report, the component is a bit more complicated than Spring Integration. Apache Camel supports a Scatter/Gather pattern using a route of the following type: ...... .split().method("sectionRequestSplitterBean", "split") .aggregationStrategy(new ReportAggregationStrategy()) with an aggregation strategy being passed on to the Splitter, the aggregation strategy implementation is the following: public class ReportAggregationStrategy implements AggregationStrategy { @Override public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { if (oldExchange == null) { Section section = newExchange.getIn().getBody(Section.class); Report report = new Report(); report.addSection(section); newExchange.getIn().setBody(report); return newExchange; } Report report = oldExchange.getIn().getBody(Report.class); Section section = newExchange.getIn().getBody(Section.class); report.addSection(section); oldExchange.getIn().setBody(report); return oldExchange; } } This completes the Apache Camel based implementation. A working sample for Camel is provided with the article - just download, extract and run "mvn test". Conclusion: Spring Integration and Apache Camel provide a simple and clean approach for the Integration problems in a typical enterprise. They are lightweight frameworks – Spring Integration builds on top of Spring portfolio and extends the familiar programming model for the Integration domain and is easy to pick up, Apache camel provides a good Java based DSL and integrates well with Spring Core, with a fairly gentle learning curve. The article does not recommend one product over the other but encourages the reader to evaluate and learn from both these frameworks. References: Spring Integration Website: http://www.springsource.org/spring-integration Apache Camel Website: http://camel.apache.org/ Spring Integration Reference: http://static.springsource.org/spring-integration/reference/htmlsingle/spring-integration-reference.html Apache Camel User Guide: http://camel.apache.org/user-guide.html Plug for my blog: http://biju-allandsundry.blogspot.com/
December 31, 2009
by Biju Kunjummen
· 101,887 Views · 3 Likes
article thumbnail
How to Create a Java EE 6 Application with JSF 2, EJB 3.1, JPA, and NetBeans IDE 6.8
Develop a web-based app based on technologies in the JEE6 specs such as Enterprise Java Beans 3.1 and JPA with the help of NetBeans IDE 6.8.
December 29, 2009
by Christopher Lam
· 723,096 Views · 3 Likes
article thumbnail
Lombok Reduces Your Boilerplate Code
In this article, I show you the power of the product I stumbled upon this week: Project Lombok enables you to modify bytecode at compile code. First, I will detail what features Lombok brings you out-of-the-box. In the second part of this article, I will describe how to extend it to generate you own code. Introduction Since the dawn of JEE, complaints have been filed regarding the complexity of coding components. I consider EJB v2 a very good example of this complexity: for just a simple EJB, you have to provide the EJB class itself and a home and an interface for each access type (local and remote). This makes it complex, error-prone and more importantly gives you less time to focus on business code where the real value is. Two initiatives show the will to decrease the amount of boilerplate code needed when coding: the Spring Framework’s motto is to decrease JEE complexity. The boilerplate code is written once in the Spring framework and only used by projects. EJB v3 has taken into account the lessons from Spring and aim to reduce boilerplate code too, making local and remote interfaces unnecessary. Eventually, the next version of the specification will make the local and remote home optional too. The goal of Project Lombok is exactly the same as the previous initiatives but in order to do so, it uses another mechanism. Annotation processing Version 5 of the Java language introduced the concept of annotations, code meta-data that could be processed at compile time and/or runtime. Unfortunately, in JDK 5, processing annotations at compile is a 2-step process. First, you have to run the apt executable to process annotations, perhaps creating or modifying source files, then compile your sources with javac. That was not the best approach, so Java 6 removes apt and make javac able to manage annotations, streamlining the process to obtain a simpler single step computing. This is the path taken by Lombok. Project Lombok Lombok’s driving feature is to create code you need from annotations in order to reduce the amount of boilerplate code you have to write. It provides you with the following annotations that will change your code (if not your life) forever: @Getter and @Setter: create getters and setters for your fields @EqualsAndHashCode: implements equals() and hashCode() @ToString: implements toString() @Data: uses the four previous features @Cleanup: closes your stream @Synchronized: synchronize on objects @SneakyThrows: throws exceptions For example, while learning to code the OO way, you were drilled into making your fields private and into writing public accessors to access these fields: public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } Since this is a bother to write, some (if not all) IDE have a feature to generate the accessors. It has some drawbacks: You have to manually remove the accessors if you remove the field It clutters your real code with boilerplate code Corollary: it takes a real effort to check whether an accessor already exist for a field in a long class Moreover, creating accessors manually is error-prone: I once searched for hours for a bug in code developed by a fellow developer and finally found the setter was wrong. Since getter / setter is only meta-data for a field, Lombok’s stance is to treat it like such: in Java, meta-data is managed with annotations. Look at the following code: import org.lombok.Getter; import org.lombok.Setter; public class Person { @Getter @Setter private String name; } I decompiled the generated class (using JAD) and it creates exactly the same bytecode, only the source code is more concise and less error-prone. When thinking, I found 3 arguments against using Lombok: The first argument against using such a strategy is that you can’t create a protected accessor like that. You’re wrong, Lombok is configurable: import lombok.AccessLevel; import org.lombok.Getter; import org.lombok.Setter; public class Person { @Getter @Setter(AccessLevel.PROTECTED) private String name; } And its true for all the provided annotations! Just look at them. The second argument against using Lombok is that you don’t know what it does behind the scene. It’s true, but the same could be said for AOP or CGLIB or whatever framework you’re using. The last argument and IMHO the only one valid enough is that it renders debugging more complex: but so is the use of Java dynamic proxies that Spring uses throughout its code, and still many projects use them. Use and installation Using Lombok is a 3-step process: Put the JAR on the classpath Add the annotation you want to use Compile with javac There’s a catch, though. Notice the last statement and the emphasis on javac. Since most (if not all) the developers you and I know focus a little bit on productivity, chances are you’re using a IDE. I do not know about NetBeans and fellows, but my favorite IDE Eclipse does not use javac to compile but its own internal compiler. Our friends from Lombok thought about that and Lombok is able to hook into Eclipse compiling process too. In order to do so, just launch lombok.jar and follow the instructions on you screen: it will just add 2 lines to your eclipse.ini. A word of advice (since I made the mistake): if you launch Eclipse with a command that takes parameters, such as a Windows shortcut, these parameters take precedence and eclipse.ini is silently ignored. Just to let you know… Lombok extensions To my knowledge, there’s currently only a single extension of Lombok called Morbok. It lets you create your classical private static final logger with just an annotation. The advantage of this is that Morbok automatically uses the fully qualified class name as the name of the logger so no more copy paste error. The disadvantage is that if you do not use Commons Logging as you logging framework, you have to configure each @Logger annotation with the framework you want to use, there’s no overall configuration: IMHO, that’s something that could be covered in the next version (is there’s one). Architecture First things first, Lombok needs a JDK 6 to compile since annotation processing is done in Java 5 with APT. For now, Lombok hooks into the compiling process immediately after the environment has built the AST for the class. It then passes the structure thus formed to each of its referenced handlers. There’s a single handler for each annotation: HandleGetter for @Getter, HandlerSetter for @Setter and so on. Handlers are, guess what, responsible for handling annotations. Extending Lombok Extending Lombok is a 3-step process: Create the annotation. Since the annotation is used at compile-time, it can be safely be discarded afterwards so its retention policy can be left to its default value (namely RetentionPolicy.SOURCE) Create the handler. A handler is a class that directly implements lombok.javac.JavacAnnotationHandler. Why directly? Because Lombok uses the ServiceProvider service and it’s one of its limitations Reference the fully qualified class name of the handler in a file named lombok.javac.JavacAnnotationHandler under META-INF/services The real coding takes place in step 2: the interface has a single method handle(AnnotationValues annotation, com.sun.tools.javac.tree.JCTree.JCAnnotation ast, JavacNode annotationNode). Notice the 2nd parameter package? It’s denotes Sun private implementation. It has some big drawbacks: The documentation is sparse if not completely unavailable. You go into unknown territory here Since the com.sun.tools.javac is not part of the public API, it can change at a moment’s notice. You can break your code with each update Remember that previously, I talked about this being only good for Java? That’s still true. If you want this new annotation to work under Eclipse, that’s another handler to write Example As an example, I coded an embryo for a @Delegate annotation. Such an annotation on a field indicates that the declaring class should have the same public methods as the field’s class and each method’s body should be a call to its delegate’s method. public class Delegator { @Delegate private DelegateObject object; ... } public class DelegateObject { public void doSomething() { ... } } The previous code should generate the same bytecode as the following code: public class Delegator { private DelegateObject object; public void doSomething() { object.doSomething(); } ... } As yet: it does not handle generics the only handler provided is for javac it is not configurable The final implementation is left for the brave readers: original sources are here in Eclipse/Maven format. Conclusion Some improvements could quickly be made to Lombok. First, I don’t like the monolithic structure the JAR has. IMHO, it could be nicely decoupled into 3 separate JARs: the Lombok agent itself, the provided annotations and associated handlers and finally, the installer. Moreover, coding two handlers for each annotation is a lost of time. What if you need to support NetBeans too? Perhaps using the Service Provider is a mistake… Finally, depending on Sun’s internal compiler API is too big a risk. I think that if Lombok could provide a facade to this API, it could be less risky for enterprise to take this road and the bridging could be made by people who understand the API (the Lombok team) and not base developers (like myself). All in all, and despite these flaws, Lombok looks like a very promising project that could well mimic Spring’s success. That’s what I wish it anyway because it’s real sideway thinking that brings much added value: good luck for the future! To go further: Project Lombok Lombok’s Javadoc Morbok From http://blog.frankel.ch
December 7, 2009
by Nicolas Fränkel
· 21,095 Views · 1 Like
article thumbnail
jQuery, Each() and Async Gets
One of the things to keep in mind when using jQuery is that nothing is a blocking call. Sure, there is a certain sequence to when things operate. But, to be safe, you should always assume that step two will happen during step one. No where is this more evident than when retrieving content from a URL and inserting that content in your page. The temptation is to write code that looks something like this $.each(json, function(index, entry) { jQuery.get(entry['url'], function(html) { // insert the HTML here. } } The problem with this is that jQuery.get is an asynchronous call. This means that once the get has fired, the each loop will continue. This can cause all kinds of trouble for you, including having a complete iteration skipped, or if you are doing some kind of concatenation prior to inserting the HTML, having HTML for one iteration showing up in the middle of another. Not exactly what you had in mind, eh? But there is a fix. Use the ajax call instead and specify async:false to force the call to complete before allowing another call. $.each(json, function(index, entry) { jQuery.ajax({ url: directory + '/' + entry['url'] , success: function(html) { // insert the HTML here. } }, async: false }); Note too that using ajax without the async: false is the same as just using get.
December 3, 2009
by Dave Bush
· 16,231 Views
  • Previous
  • ...
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×