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
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest Frameworks Topics

article thumbnail
Tracking Exceptions - Part 5 - Scheduling With Spring
It seems that I'm finally getting close to the end of this series of blogs on Error Tracking using Spring and for those who haven’t read any blogs in the series I’m writing a simple, but almost industrial strength, Spring application that scans for exceptions in log files and then generates a report. From the first blog in the series, these were my initial requirements: Search a given directory and its sub-directories (possibly) looking for files of a particular type. If a file is found then check its date: does it need to be searched for errors? If the file is young enough to be checked then validate it, looking for exceptions. If it contains exceptions, are they the ones we’re looking for or have they been excluded? If it contains the kind of exceptions we’re after, then add the details to a report. When all the files have been checked, format the report ready for publishing. Publish the report using email or some other technique. The whole thing will run at a given time every day This blog takes a look at meeting requirement number 8: "The whole thing will run at a given time every day" and this means implementing some kind of scheduling. Now, Java has been around for what seems like a very long time, which means that there are a number of ways of scheduling a task. These range from: Using a simple thread with a long sleep(...). Using Timer and TimerTask objects. Using a ScheduledExecutorService. Using Spring’s TaskExecutor and TaskScheduler classes. Using Spring’s @EnableScheduling and @Scheduled annotations (Spring 3.1 onwards). Using a more professional schedular. The more professional variety of schedulers range from Quartz (free) to Obsidian (seemingly much more advanced, but costs money). Spring, as you might expect, includes Quartz Scheduler support; in fact there are two ways of integrating the Quartz Scheduler into your Spring app and these are: Using a JobDetailBean Using a MethodInvokingJobDetailFactoryBean. For this application, I’m using the Spring’s Quartz integration together with a MethodInvokingJobDetailFactoryBean; the reason is that using Quartz allows me to configure my schedule using a a cron expression and MethodInvokingJobDetailFactoryBean can be configured quickly and simply using a few lines of XML. The cron expression technique used by Spring and Quartz has been shamelessly taken from Unix’s cron scheduler. For more information on how Quartz deals with cron expressions, take a look at the Quartz cron page. If you need help in creating your own cron expressions then you’ll find that Cron Maker is a really useful utility. The first thing to do when setting up Spring and Quartz is to include the following dependencies to your POM project file: org.springframework spring-context-support ${org.springframework-version} commons-logging commons-logging org.springframework spring-tx ${org.springframework-version} org.quartz-scheduler quartz 1.8.6 This is fairly straight forward with one tiny ’Gotcha’ at the end. Firstly Spring’s Quartz support is located in the spring-context-support-3.2.7.RELEASE.jar (substitute your Spring version number as applicable). Secondly, you also need to include the Spring transaction library - spring-td-3.2.7.RELEASE.jar. Lastly, you need to include a version of the Quartz scheduler; however, be careful as Spring 3.x and Quartz 2.x do not work together "out of the box" (although if you look around there are ad-hoc fixes to be found). I've used Quartz version 1.8.6, which does exactly what I need it to do. The next thing to do is to sort out the XML configuration and this involves three steps: Create an instance of a MethodInvokingJobDetailFactoryBean. This has two properties: the name of the bean that you want to call at a scheduled interval and the name of the method on that bean that you want to invoke. Couple the MethodInvokingJobDetailFactoryBean to a cron expression using a CronTriggerFactoryBean Finally, schedule the whole caboodle using a SchedulerFactoryBean Having configured these three beans, you get some XML that looks something like this: Note that I’ve use a place-holder for my cron expression. The actual cron expression can be found in the app.properties file: # run every morning at 2 AM cron.expression=0 0 2 * * ? # Use this to test the app (every minute) #cron.expression=0 0/1 * * * ? Here, I’ve got two expressions: one that schedules the job to run at 2AM every morning and another, commented out, that runs the job every minute. This is an instance of the app not quite being industrial strength. If there were a 'proper' app then I'd probably be using a different set of properties in every environment (DEV, UAT and production etc.). There are only a couple of steps left before this app can be released and the first one of these is creating an executable JAR file. More on that next time. The code for this blog is available on Github at: https://github.com/roghughe/captaindebug/tree/master/error-track. If you want to look at other blogs in this series take a look here... Tracking Application Exceptions With Spring Tracking Exceptions With Spring - Part 2 - Delegate Pattern Error Tracking Reports - Part 3 - Strategy and Package Private Tracking Exceptions - Part 4 - Spring's Mail Sender
April 25, 2014
by Roger Hughes
· 7,361 Views
article thumbnail
Circuit Breaker Pattern in Apache Camel
Camel is very often used in distributed environments for accessing remote resources. Remote services may fail for various reasons and periods. For services that are temporarily unavailable and recoverable after short period of time, a retry strategy may help. But some services can fail or hang for longer period of time making the calling application unresponsive and slow. A good strategy to prevent from cascading failures and exhaustion of critical resources is the Circuit Breaker pattern described by Michael Nygard in the Release It! book. Circuit Breaker is a stateful pattern that wraps the failure-prone resource and monitors for errors. Initially the Circuit Breaker is in closed state and passes all calls to the wrapped resource. When the failures reaches a certain threshold, the circuit moves to open state where it returns error to the caller without actually calling the wrapped resource. This prevents from overloading the already failing resource. While at this state, we need a mechanism to detect whether the failures are over and start calling the protected resource. This is where the third state called half-open comes into play. This state is reached after a certain time following the last failure. At this state, the calls are passed through to the protected resource, but the result of the call is important. If the call is successful, it is assumed that the protected resource has recovered and the circuit is moved into closed state, and if the call fails, the timeout is reset, and the circuit is moved back to open state where all calls are rejected. Here is the state diagram of Circuit Breaker from Martin Fowler's post: How Circuit Breaker is implemented in Camel? Circuit Breaker is available in the latest snapshot version of Camel as a Load balancer policy. Camel Load Balancer already has policies for Round Robin, Random, Failover, etc. and now also CircuiBreaker policy. Here is an example load balancer that uses Circuit Breaker policy with threshold of 2 errors and halfOpenAfter timeout of 1 second. Notice also that this policy applies only to errors caused by MyCustomException. new RouteBuilder() { public void configure() { from("direct:start").loadBalance() .circuitBreaker(2, 1000L, MyCustomException.class) .to("mock:result"); } }; And here is the same example using Spring XML DSL: MyCustomException
April 16, 2014
by Bilgin Ibryam
· 18,570 Views · 1 Like
article thumbnail
Spring Test with thymeleaf for Views
I am a recent convert to thymeleaf for view templating in Spring based web applications, preferring it over jsp's. All the arguments that thymeleaf documentation makes on why thymeleaf over jsp holds water and I am definitely sold. One of the big reasons for me, apart from being able to preview the template, is the way the view is rendered at runtime. Whereas the application stack has to defer the rendering of jsp to the servlet container, it has full control over the rendering of thymeleaf templates. To clarify this a little more, with jsp as the view technology an application only returns the location of the jsp and it is upto the servlet container to render the jsp. So why again is this a big reason - because using the mvc test support in spring-test module, now the actual rendered content can be asserted on rather than just the name of the view. Consider a sample Spring MVC controller : @Controller @RequestMapping("/shop") public class ShopController { ... @RequestMapping("/products") public String listProducts(Model model) { model.addAttribute("products", this.productRepository.findAll()); return "products/list"; } } Had the view been jsp based, I would have had a test which looks like this: @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = SampleWebApplication.class) public class ShopControllerWebTests { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } @Test public void testListProducts() throws Exception { this.mockMvc.perform(get("/shop/products")) .andExpect(status().isOk()) .andExpect(view().name("products/list")); } } the assertion is only on the name of the view. Now, consider a test with thymeleaf used as the view technology: @Test public void testListProducts() throws Exception { this.mockMvc.perform(get("/shop/products")) .andExpect(status().isOk()) .andExpect(content().string(containsString("Dummy Book1"))); } Here, I am asserting on the actual rendered content. This is really good, whereas with jsp I would had to validate that the jsp is rendered correctly at runtime with a real container, with thymeleaf I can validate that rendering is clean purely using tests.
April 15, 2014
by Biju Kunjummen
· 27,237 Views · 2 Likes
article thumbnail
How to Setup Remote Debug with WebLogic Server and Eclipse
Here is how I enable remote debugging with WebLogic Server (11g) and Eclipse IDE. (Actually the java option is for any JVM, just the instruction here is WLS specific.) 1. Edit /bin/setDomainEnv.sh file and add this on top: JAVA_OPTIONS="$JAVA_OPTIONS -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y" The suspend=y will start your server and wait for you to connect with IDE before continue. If you don't want this, then set to suspend=n instead. 2. Start/restart your WLS with /bin/startWebLogic.sh 3. Once WLS is running, you may connect to it using Eclipse IDE. Go to Menu: Run > Debug Configuration ... > Remote Java Application and create a new entry. Ensure your port number is matching to what you used above. Read more java debugging options here: http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#DebuggingOptions
April 12, 2014
by Zemian Deng
· 73,317 Views
article thumbnail
Tracking Exceptions - Part 4 - Spring's Mail Sender
If you've read any of the previous blogs in this series, you may remember that I'm developing a small but almost industrial strength application that searches log files for exceptions. You may also remember that I now have a class that can contain a whole bunch of results that will need sending to any one whose interested. This will be done by implementing my simple Publisher interface shown below. public interface Publisher { public boolean publish(T report);} If you remember, the requirement was: 7 . Publish the report using email or some other technique. In this blog I’m dealing with the concrete part of the requirement: sending a report by email. As this is a Spring app, then the simplest way of sending an email is to use Spring’s email classes. Unlike those stalwarts of the Spring API, template classes such as JdbcTemplate and JmsTemplate, the Spring email classes are based around a couple of interfaces and their implementations. The interfaces are: MailSender JavaMailSender extends MailSender MailMessage …and the implementations are: JavaMailSenderImpl implements JavaMailSender SimpleMailMessage implements MailMessage Note that these are the ‘basic’ classes; you can send nicer looking, more sophisticated email content using classes such as: MimeMailMessage, MimeMailMessageHelper, ConfigurableMimeFileTypeMap and MimeMessagePreparator. Before getting down to some code, there’s the little matter of project configuration. To use the Spring email classes, you need the following entry in your Maven POM file: javax.mail mail 1.4 This ensures that the underlying Java Mail classes are available to your application. Once the Java Mail classes are configured in the build, the next thing to do is to set up the Spring XML config. For the purposes of this app, which is sending out automated reports, I’ve included two Spring beans: mailSender and mailMessage.mailSender, is a JavaMailSenderImpl instance configured to use a specific SMTP mail server, with all other properties, such as TCP port, left as defaults. The second Spring bean is mailMessage, an instance of SimpleMailMessage. This time I’ve pre-configured three properties: ‘to’, ‘from’ and ‘subject’. This is because, being automated messages, these values are always identical. You can of course configure these programatically, something you’d probably need to do if you were creating a mail GUI. All this XML makes the implementation of the Publisher very simple. @Service public class EmailPublisher implements Publisher { private static final Logger logger = LoggerFactory.getLogger(EmailPublisher.class); @Autowired private MailSender mailSender; @Autowired private SimpleMailMessage mailMessage; @Override public boolean publish(T report) { logger.debug("Sending report by email..."); boolean retVal = false; try { String message = (String) report; mailMessage.setText(message); mailSender.send(mailMessage); retVal = true; } catch (Exception e) { logger.error("Can't send email... " + e.getMessage(), e); } return retVal;} } The Publisher class contains one method: publish, which takes a generic argument T report. This, as I’ve said before, has to be the same type as the argument returned by the Formatter implementation from my previous blog. There are only really three steps in this code to consider: firstly, the generic T is cast to a String (this is where it’ll all fall over if the argument T report isn’t a String. The second step is to attach the email’s text to the mailMessage and then to send the message using mailSender.send(…). The final step is fulfil the Publisher contract by returning true, unless the email fails to send in which case the exception is logged and the return value is false. In terms of developing the code that’s about it. The next step is to sort out the scheduling, so that the report is generated on time, but more on that later… The code for this blog is available on Github at: https://github.com/roghughe/captaindebug/tree/master/error-track. If you want to look at other blogs in this series take a look here… Tracking Application Exceptions With Spring Tracking Exceptions With Spring - Part 2 - Delegate Pattern Error Tracking Reports - Part 3 - Strategy and Package Private
April 11, 2014
by Roger Hughes
· 13,477 Views · 1 Like
article thumbnail
Developing an iOS Native App with Ionic
In my current project, I've been helping a client develop a native iOS app for their customers. It's written mostly in Objective-C and talks to a REST API. I talked about how we documented our REST API a couple days ago. We developed a prototype for this application back in December, using AngularJS and Bootstrap. Rather than using PhoneGap, we loaded our app in a UIWebView. It all seemed to work well until we needed to read an activation code with the device's camera. Since we didn't know how to do OCR in JavaScript, we figured a mostly-native app was the way to go. We hired an outside company to do iOS development in January and they've been developing the app since the beginning of February. In the last couple weeks, we encountered some screens that seemed fitting for HTML5, so we turned back to our AngularJS prototype. The prototype used Bootstrap heavily, but we quickly learned it didn't look like an iOS 7 app, which is what our UX Designer requested. A co-worker pointed out Ionic, developed by Drifty. It's basically Bootstrap for Native, so the apps you develop look and behave like a mobile application. What is Ionic? Free and open source, Ionic offers a library of mobile-optimized HTML, CSS and JS components for building highly interactive apps. Built with Sass and optimized for AngularJS. I started developing with Ionic a few weeks ago. Using its CSS classes and AngularJS directives, I was able to create several new screens in a matter of days. Most of the time, I was learning new things: how to override its back button behavior (to launch back into the native app), how to configure routes with ui-router, and how to make the $ionicLoading service look native. Now that I know a lot of the basics, I feel like I can really crank out some code. Tip: I learned how subviews work with ui-router thanks to a YouTube video of Tim Kindberg on Angular UI-Router. However, subviews never fully made sense until I saw Jared Bell's diagram. To demonstrate how easy it is to use Ionic, I whipped up a quick example application. You can get the source on GitHub at https://github.com/mraible/boot-ionic. The app is a refactored version of Josh Long's x-auth-security that uses Ionic instead of raw AngularJS and Bootstrap. To keep things simple, I did not develop the native app that wraps the HTML. Below are the steps I used to convert from AngularJS + Bootstrap to Ionic. If you want to convert a simple AngularJS app to use Ionic, hopefully this will help. 1. Download Ionic and add it to your project. Ionic 1.0 Beta was released earlier this week. You can download it from here. Add its files to your project. In this example, I added them to src/main/resources/public. In my index.html, I removed Bootstrap's CSS and replaced it with Ionic's. - + - + Next, I replaced Angular, Bootstrap and jQuery's JavaScript references. - - - + - What about WebJars? You might ask - why not use WebJars? You can, once this pull request is accepted and an updated version is deployed to Maven central. Here's how the application would change. 2. Change from Angular's Router to ui-router. Ionic uses ui-router for matching URLs and loading particular pages. The raw Angular routing looks pretty similar to how it does with ui-router, except it uses a $stateProvider service instead of $routeProvider. You'll notice I also added 'ionic' as a dependency. -angular.module('exampleApp', ['ngRoute', 'ngCookies', 'exampleApp.services']) +angular.module('exampleApp', ['ionic', 'ngCookies', 'exampleApp.services']) .config( - [ '$routeProvider', '$locationProvider', '$httpProvider', function($routeProvider, $locationProvider, $httpProvider) { + [ '$stateProvider', '$urlRouterProvider', '$httpProvider', function($stateProvider, $urlRouterProvider, $httpProvider) { - $routeProvider.when('/create', { templateUrl: 'partials/create.html', controller: CreateController}); + $stateProvider.state('create', {url: '/create', templateUrl: 'partials/create.html', controller: CreateController}) + .state('edit', {url: '/edit/:id', templateUrl: 'partials/edit.html', controller: EditController}) + .state('login', {url: '/login', templateUrl: 'partials/login.html', controller: LoginController}) + .state('index', {url: '/index', templateUrl: 'partials/index.html', controller: IndexController}); - $routeProvider.when('/edit/:id', { templateUrl: 'partials/edit.html', controller: EditController}); - $routeProvider.when('/login', { templateUrl: 'partials/login.html', controller: LoginController}); - $routeProvider.otherwise({templateUrl: 'partials/index.html', controller: IndexController}); - - $locationProvider.hashPrefix('!'); + $urlRouterProvider.otherwise('/index'); 3. Add Ionic elements to your index.html. In contrast to Bootstrap's navbar, Ionic has header and footer elements. Rather than using a ng-view directive, you use an . It's a pretty slick setup once you understand it, especially since they allow you to easily override back-button behavior and nav buttons. - - - - - - {{error} - - + + + {{error} + + + + Logout + + 4. Change your templates to use and . After routes are migrated and basic navigation is working, you'll need to modify your templates to use and . Here's a diff from the most complicated page in the app. - - Create - - - News - + + + + + + + + + + - - - - Remove - Edit - - {{newsEntry.date | date} - {{newsEntry.content} - - + + + {{newsEntry.date | date} + {{newsEntry.content} + + + + I did migrate to use an with delete/options buttons, so some additional JavaScript changes were needed. -function IndexController($scope, NewsService) { +function IndexController($scope, $state, NewsService) { $scope.newsEntries = NewsService.query(); + $scope.data = { + showDelete: false + }; + $scope.deleteEntry = function(newsEntry) { newsEntry.$remove(function() { $scope.newsEntries = NewsService.query(); }); }; + + $scope.itemButtons = [{ + text: 'Edit', + type: 'button-assertive', + onTap: function (item) { + $state.go('edit', {id: item.id}); + } + }]; } Screenshots After making all these changes, the app looks pretty good in Chrome. Tips and Tricks In additional to figuring out how to use Ionic, I discovered a few other tidbits along the way. First of all, we had a different default color for the header. Since Ionic uses generic color names (e.g. light, stable, positive, calm), I found it easy to change the default value for "positive" and then continue to use their class names. Modifying CSS variable colors To modify the base color for "positive", I cloned the source, and modified scss/_variables.scss. $light: #fff !default; $stable: #f8f8f8 !default; -$positive: #4a87ee !default; +$positive: #589199 !default; $calm: #43cee6 !default; $balanced: #66cc33 !default; $energized: #f0b840 !default; After making this change, I ran "grunt" and copied dist/css/ionic.css into our project. iOS Native Integration Our app uses a similar token-based authentication mechanism as x-auth-security, except its backed by Crowd. However, since users won't be logging directly into the Ionic app, we added the "else" clause in app.js to allow a token to be passed in via URL. We also allowed the backend API path to be overridden. /* Try getting valid user from cookie or go to login page */ var originalPath = $location.path(); $location.path("/login"); var user = $cookieStore.get('user'); if (user !== undefined) { $rootScope.user = user; $http.defaults.headers.common[xAuthTokenHeaderName] = user.token; $location.path(originalPath); } else { // token passed in from native app var authToken = $location.search().token; if (authToken) { $http.defaults.headers.common['X-Auth-Token'] = authToken; } } // allow overriding the base API path $rootScope.apiPath = '/api/v1.0'; if ($location.search().apiPath) { $rootScope.apiPath = $location.search().apiPath; } By adding this logic, the iOS app can pull up any particular page in a webview and let the Ionic app talk to the API. Here's what the Objective-C code looks like: NSString *versionNumber = @"v1.0"; NSString *apiPath = @"https://server.com/api/"; NSString *authToken = [TemporaryDataStore sharedInstance].authToken; // webapp is a symbolic link to the Ionic app, created with Angular Seed NSString *htmlFilePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"webapp/app"]; // Note: We need to do it this way because 'fileURLWithPath:' would encode the '#' to '%23" which breaks the html page NSURL *htmlFileURL = [NSURL fileURLWithPath:htmlFilePath]; NSString *webappURLPath = [NSString stringWithFormat:@"%@#/news?apiPath=%@%@&token=%@", htmlFileURL.absoluteString, apiPath, versionNumber, authToken]; // Now convert the string to a URL (doesn't seem to encode the '#' this way) NSURL *webappURL = [NSURL URLWithString:webappURLPath]; [super updateWithURL:webappURL]; We also had to write some logic to navigate back to the native app. We used a custom URL scheme to do this, and the Ionic app simply called it. To override the default back button, I added an "ng-controller" attribute to and added a custom back button. To detect if the app was loaded by iOS (vs. a browser, which we tested in), we used the following logic: // set native app indicator if (document.location.toString().indexOf('appName.app') > -1) { $rootScope.isNative = true; } Our Ionic app has three entry points, defined by "stateName1", "stateName2" and "stateName3" in this example. The code for our NavController handles navigating back normally (when in a browser) or back to the native app. The "appName" reference below is a 3-letter acronym we used for our app. .controller('NavController', function($scope, $ionicNavBarDelegate, $state) { $scope.goBack = function() { if ($scope.isNative && backToNative($state)) { location.href='appName-ios://back'; } else { $ionicNavBarDelegate.back(); } }; function backToNative($state) { var entryPoints = ['stateName1', 'stateName2', 'stateName3']; return entryPoints.some(function (entry) { return $state.current === $state.get(entry); }); } }) Summary I've enjoyed working with Ionic over the last month. The biggest change I've had to make to our AngularJS app has been to integrate ui-router. Apart from this, the JavaScript didn't change much. However, the HTML had to change quite a bit. As far as CSS is concerned, I found myself tweaking things to fit our designs, but less so than I did with Bootstrap. When I've run into issues with Ionic, the community has been very helpful on their forum. It's the first forum I've used that's powered by Discourse, and I dig it. You can find the source from this article in my boot-ionic project. Clone it and run "mvn spring-boot:run", then open http://localhost:8080. If you're looking to create a native app using HTML5 technologies, I highly recommend you take a look at Ionic. We're glad we did. Angular 2.0 will target mobile apps and Ionic is already making them look pretty damn good.
April 7, 2014
by Matt Raible
· 14,303 Views
article thumbnail
Spring-boot and Scala
There is actually nothing very special about writing a Spring-boot web application purely using Scala, it just works! In this blog entry, I will slowly transform a Java based Spring-boot application completely to Scala - the Java based sample is available at this github location - https://github.com/bijukunjummen/spring-boot-mvc-test To start with, I had the option of going with either a maven based build or gradle based build - I opted to go with a gradle based build as gradle has a greatscala plugin, so for scala support the only changes to a build.gradle build script is the following: ... apply plugin: 'scala' ... jar { baseName = 'spring-boot-scala-web' version = '0.1.0' } dependencies { ... compile 'org.scala-lang:scala-library:2.10.2' ... } Essentially adding in the scala plugin and specifying the version of the scala-library. Now, I have one entity, a Hotel class, it transforms to the following with Scala: package mvctest.domain .... @Entity class Hotel { @Id @GeneratedValue @BeanProperty var id: Long = _ @BeanProperty var name: String = _ @BeanProperty var address: String = _ @BeanProperty var zip: String = _ } Every property is annotated with @BeanProperty annotation to instruct scala to generate the Java bean based getter and setter on the variables. With the entity in place a Spring-data repository for CRUD operations on this entity transforms from: import mvctest.domain.Hotel; import org.springframework.data.repository.CrudRepository; public interface HotelRepository extends CrudRepository { } to the following in Scala: import org.springframework.data.repository.CrudRepository import mvctest.domain.Hotel import java.lang.Long trait HotelRepository extends CrudRepository[Hotel, Long] And the Scala based controller which uses this repository to list the Hotels - vi... import org.springframework.web.bind.annotation.RequestMapping import org.springframework.stereotype.Controller import mvctest.service.HotelRepository import org.springframework.beans.factory.annotation.Autowired import org.springframework.ui.Model @Controller @RequestMapping(Array("/hotels")) class HotelController @Autowired() (private val hotelRepository: HotelRepository) { @RequestMapping(Array("/list")) def list(model: Model) = { val hotels = hotelRepository.findAll() model.addAttribute("hotels", hotels) "hotels/list" } } Here the constructor autowiring of the HotelRepository just works!. Do note the slightly awkward way of specifying the @Autowired annotation for constructor based injection. Finally, Spring-boot based application requires a main class to bootstrap the entire application, where this bootstrap class looks like this with Java: @Configuration @EnableAutoConfiguration @ComponentScan public class SampleWebApplication { public static void main(String[] args) { SpringApplication.run(SampleWebApplication.class, args); } } In scala, though I needed to provide two classes, one to specify the annotation and other to bootstrap the application, there may be better way to do this(blame it on my lack of Scala depth!) - package mvctest import org.springframework.context.annotation.Configuration import org.springframework.boot.autoconfigure.EnableAutoConfiguration import org.springframework.context.annotation.ComponentScan import org.springframework.boot.SpringApplication @Configuration @EnableAutoConfiguration @ComponentScan class SampleConfig object SampleWebApplication extends App { SpringApplication.run(classOf[SampleConfig]); } and that's it, with this set-up the entire application just works, the application can be started up with the following: ./gradlew build && java -jar build/libs/spring-boot-scala-web-0.1.0.jar and the sample endpoint listing the hotels accessed at this url: http://localhost:8080/hotels/list I have the entire git project available at this github location: https://github.com/bijukunjummen/spring-boot-scala-web In conclusion, Scala can be considered a first class citizen for a Spring-boot based application and there is no special configuration required to get a Scala based Spring-boot application to work. It just works!
April 2, 2014
by Biju Kunjummen
· 71,215 Views · 11 Likes
article thumbnail
Add Java 8 support to Eclipse Kepler
want to add java 8 support to kepler? java 8 has not yet landed in our standard download packages . but you can add it to your existing eclipse kepler package. i’ve got three different eclipse installations running java 8: a brand new kepler sr2 installation of the eclipse ide for java developers; a slightly used kepler sr1 installation of the eclipse for rcp/rap developers (with lots of other features already added); and a nightly build (dated march 24/2014) of eclipse 4.4 sdk. the jdt team recommends that you start from kepler sr2, the second and final service release for kepler (but using the exact same steps, i’ve installed it into kepler sr1 and sr2 packages). there are some detailed instructions for adding java 8 support by installing a feature patch in the eclipsepedia wiki . the short version is this: from kepler sr2, use the “help > install new software…” menu option to open the “available software” dialog; enter http://download.eclipse.org/eclipse/updates/4.3-p-builds/ into the “work with” field (highlighted below); put a checkbox next to “eclipse java 8 support (for kepler sr2)” (highlighted below); click “next”, click “next”, read and accept the license, and click “finish” watch the pretty progress bar move relatively quickly across the bottom of the window; and restart eclipse when prompted. select “help > install new software…” to open the available software dialog. voila! support for java 8 is installed. if you’ve already got the java 8 jdk installed and the corresponding jre is the default on your system, you’re done. if you’re not quite ready to make the leap to a java 8 jre, there’s still hope (my system is still configured with java 7 as the default). install the java 8 jdk; open the eclipse preferences, and navigate to “java > installed jres”; java runtime environment preferences click “add…”; select “standard vm”, click “next”; enter the path to the java 8 jre (note that this varies depending on platform, and how you obtain and install the bits); java 8 jre definition click “finish”. before closing the preferences window, you can set your workspace preference to use the newly-installed java 8 jre. or, if you’re just planning to experiment with java 8 for a while, you can configure this on a project-by-project basis. in the create a java project dialog, specify that your project will use a javase-1.8 jre. it’s probably better to do this on the project as this will become a project setting that will follow the project into your version control system. next step… learn how wrong my initial impressions of java 8 were (hint: it’s far better). the lambda is so choice. if you have the means, i highly recommend picking one up. about these ads
March 30, 2014
by Wayne Beaton
· 67,729 Views · 1 Like
article thumbnail
Servlet 3.0 ServletContainerInitializer and Spring WebApplicationInitializer
Spring WebApplicationInitializer provides a programatic way to configure the Spring DispatcherServlet and ContextLoaderListener in Servlet 3.0+ compliant servlet containers , rather than adding this configuration through a web.xml file. This is a quick note to show how implementation through WebApplicationInitializer interface internally works, given that this interface does not derive from any Servlet related interface! The answer is the ServletContainerInitializer interface introduced with Servlet 3.0 specification, implementors of this interface are notified during the context startup phase and can perform any programatic registration through the provided ServletContext. Spring implements the ServletContainerInitializer through SpringServletContainerInitializer class. Per the Servlet specs, this implementation must be declared in a META-INF/services/javax.servlet.ServletContainerInitializer file of the libraries jar file - Spring declares this in spring-web*.jar jar file and has an entry `org.springframework.web.SpringServletContainerInitializer` SpringServletContainerInitializer class has a @HandlerTypes annotation with a value of WebApplicationInitializer, this means that the Servlet container will scan for classes implementing the WebApplicationInitializer implementation and call the onStartUp method with these classes and that is where the WebApplicationInitializer fits in. A little convoluted, but the good thing is all these details are totally abstracted away within the spring-web framework and the developer only has to configure an implementation of WebApplicationInitializer and live in a web.xml free world.
March 29, 2014
by Biju Kunjummen
· 16,286 Views
article thumbnail
Documenting Your Spring API with Swagger
over the last several months, i've been developing a rest api using spring boot . my client hired an outside company to develop a native ios app, and my development team was responsible for developing its api. our main task involved integrating with epic , a popular software system used in health care. we also developed a crowd -backed authentication system, based loosely on philip sorst's angular rest security . to document our api, we used spring mvc integration for swagger (a.k.a. swagger-springmvc). i briefly looked into swagger4spring-web , but gave up quickly when it didn't recognize spring's @restcontroller. we started with swagger-springmvc 0.6.5 and found it fairly easy to integrate. unfortunately, it didn't allow us to annotate our model objects and tell clients which fields were required. we were quite pleased when a new version (0.8.2) was released that supports swagger 1.3 and its @apimodelproperty. what is swagger? the goal of swagger is to define a standard, language-agnostic interface to rest apis which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. to demonstrate how swagger works, i integrated it into josh long's x-auth-security project. if you have a boot-powered project, you should be able to use the same steps. 1. add swagger-springmvc dependency to your project. com.mangofactory swagger-springmvc 0.8.2 note: on my client's project, we had to exclude "org.slf4j:slf4j-log4j12" and add "jackson-module-scala_2.10:2.3.1" as a dependency. i did not need to do either of these in this project. 2. add a swaggerconfig class to configure swagger. the swagger-springmvc documentation has an example of this with a bit more xml. package example.config; import com.mangofactory.swagger.configuration.jacksonscalasupport; import com.mangofactory.swagger.configuration.springswaggerconfig; import com.mangofactory.swagger.configuration.springswaggermodelconfig; import com.mangofactory.swagger.configuration.swaggerglobalsettings; import com.mangofactory.swagger.core.defaultswaggerpathprovider; import com.mangofactory.swagger.core.swaggerapiresourcelisting; import com.mangofactory.swagger.core.swaggerpathprovider; import com.mangofactory.swagger.scanners.apilistingreferencescanner; import com.wordnik.swagger.model.*; import org.springframework.beans.factory.annotation.autowired; import org.springframework.beans.factory.annotation.value; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.componentscan; import org.springframework.context.annotation.configuration; import java.util.arraylist; import java.util.arrays; import java.util.list; import static com.google.common.collect.lists.newarraylist; @configuration @componentscan(basepackages = "com.mangofactory.swagger") public class swaggerconfig { public static final list default_include_patterns = arrays.aslist("/news/.*"); public static final string swagger_group = "mobile-api"; @value("${app.docs}") private string docslocation; @autowired private springswaggerconfig springswaggerconfig; @autowired private springswaggermodelconfig springswaggermodelconfig; /** * adds the jackson scala module to the mappingjackson2httpmessageconverter registered with spring * swagger core models are scala so we need to be able to convert to json * also registers some custom serializers needed to transform swagger models to swagger-ui required json format */ @bean public jacksonscalasupport jacksonscalasupport() { jacksonscalasupport jacksonscalasupport = new jacksonscalasupport(); //set to false to disable jacksonscalasupport.setregisterscalamodule(true); return jacksonscalasupport; } /** * global swagger settings */ @bean public swaggerglobalsettings swaggerglobalsettings() { swaggerglobalsettings swaggerglobalsettings = new swaggerglobalsettings(); swaggerglobalsettings.setglobalresponsemessages(springswaggerconfig.defaultresponsemessages()); swaggerglobalsettings.setignorableparametertypes(springswaggerconfig.defaultignorableparametertypes()); swaggerglobalsettings.setparameterdatatypes(springswaggermodelconfig.defaultparameterdatatypes()); return swaggerglobalsettings; } /** * api info as it appears on the swagger-ui page */ private apiinfo apiinfo() { apiinfo apiinfo = new apiinfo( "news api", "mobile applications and beyond!", "https://helloreverb.com/terms/", "[email protected]", "apache 2.0", "http://www.apache.org/licenses/license-2.0.html" ); return apiinfo; } /** * configure a swaggerapiresourcelisting for each swagger instance within your app. e.g. 1. private 2. external apis * required to be a spring bean as spring will call the postconstruct method to bootstrap swagger scanning. * * @return */ @bean public swaggerapiresourcelisting swaggerapiresourcelisting() { //the group name is important and should match the group set on apilistingreferencescanner //note that swaggercache() is by defaultswaggercontroller to serve the swagger json swaggerapiresourcelisting swaggerapiresourcelisting = new swaggerapiresourcelisting(springswaggerconfig.swaggercache(), swagger_group); //set the required swagger settings swaggerapiresourcelisting.setswaggerglobalsettings(swaggerglobalsettings()); //use a custom path provider or springswaggerconfig.defaultswaggerpathprovider() swaggerapiresourcelisting.setswaggerpathprovider(apipathprovider()); //supply the api info as it should appear on swagger-ui web page swaggerapiresourcelisting.setapiinfo(apiinfo()); //global authorization - see the swagger documentation swaggerapiresourcelisting.setauthorizationtypes(authorizationtypes()); //every swaggerapiresourcelisting needs an apilistingreferencescanner to scan the spring request mappings swaggerapiresourcelisting.setapilistingreferencescanner(apilistingreferencescanner()); return swaggerapiresourcelisting; } @bean /** * the apilistingreferencescanner does most of the work. * scans the appropriate spring requestmappinghandlermappings * applies the correct absolute paths to the generated swagger resources */ public apilistingreferencescanner apilistingreferencescanner() { apilistingreferencescanner apilistingreferencescanner = new apilistingreferencescanner(); //picks up all of the registered spring requestmappinghandlermappings for scanning apilistingreferencescanner.setrequestmappinghandlermapping(springswaggerconfig.swaggerrequestmappinghandlermappings()); //excludes any controllers with the supplied annotations apilistingreferencescanner.setexcludeannotations(springswaggerconfig.defaultexcludeannotations()); // apilistingreferencescanner.setresourcegroupingstrategy(springswaggerconfig.defaultresourcegroupingstrategy()); //path provider used to generate the appropriate uri's apilistingreferencescanner.setswaggerpathprovider(apipathprovider()); //must match the swagger group set on the swaggerapiresourcelisting apilistingreferencescanner.setswaggergroup(swagger_group); //only include paths that match the supplied regular expressions apilistingreferencescanner.setincludepatterns(default_include_patterns); return apilistingreferencescanner; } /** * example of a custom path provider */ @bean public apipathprovider apipathprovider() { apipathprovider apipathprovider = new apipathprovider(docslocation); apipathprovider.setdefaultswaggerpathprovider(springswaggerconfig.defaultswaggerpathprovider()); return apipathprovider; } private list authorizationtypes() { arraylist authorizationtypes = new arraylist<>(); list authorizationscopelist = newarraylist(); authorizationscopelist.add(new authorizationscope("global", "access all")); list granttypes = newarraylist(); loginendpoint loginendpoint = new loginendpoint(apipathprovider().getappbasepath() + "/user/authenticate"); granttypes.add(new implicitgrant(loginendpoint, "access_token")); return authorizationtypes; } @bean public swaggerpathprovider relativeswaggerpathprovider() { return new apirelativeswaggerpathprovider(); } private class apirelativeswaggerpathprovider extends defaultswaggerpathprovider { @override public string getappbasepath() { return "/"; } @override public string getswaggerdocumentationbasepath() { return "/api-docs"; } } } the apipathprovider class referenced above is as follows: package example.config; import com.mangofactory.swagger.core.swaggerpathprovider; import org.springframework.beans.factory.annotation.autowired; import org.springframework.web.util.uricomponentsbuilder; import javax.servlet.servletcontext; public class apipathprovider implements swaggerpathprovider { private swaggerpathprovider defaultswaggerpathprovider; @autowired private servletcontext servletcontext; private string docslocation; public apipathprovider(string docslocation) { this.docslocation = docslocation; } @override public string getapiresourceprefix() { return defaultswaggerpathprovider.getapiresourceprefix(); } public string getappbasepath() { return uricomponentsbuilder .fromhttpurl(docslocation) .path(servletcontext.getcontextpath()) .build() .tostring(); } @override public string getswaggerdocumentationbasepath() { return uricomponentsbuilder .fromhttpurl(getappbasepath()) .pathsegment("api-docs/") .build() .tostring(); } @override public string getrequestmappingendpoint(string requestmappingpattern) { return defaultswaggerpathprovider.getrequestmappingendpoint(requestmappingpattern); } public void setdefaultswaggerpathprovider(swaggerpathprovider defaultswaggerpathprovider) { this.defaultswaggerpathprovider = defaultswaggerpathprovider; } } in src/main/resources/application.properties , add an "app.docs" property. this will need to be changed as you move your application from local -> test -> staging -> production. spring boot's externalized configuration makes this fairly simple. app.docs=http://localhost:8080 3. verify swagger produces json. after completing the above steps, you should be able to see the json swagger generates for your api. open http://localhost:8080/api-docs in your browser or curl http://localhost:8080/api-docs . { "apiversion": "1", "swaggerversion": "1.2", "apis": [ { "path": "http://localhost:8080/api-docs/mobile-api/example_newscontroller", "description": "example.newscontroller" } ], "info": { "title": "news api", "description": "mobile applications and beyond!", "termsofserviceurl": "https://helloreverb.com/terms/", "contact": "[email protected]", "license": "apache 2.0", "licenseurl": "http://www.apache.org/licenses/license-2.0.html" } } 4. copy swagger ui into your project. swagger ui is a good-looking javascript client for swagger's json. i integrated it using the following steps: git clone https://github.com/wordnik/swagger-ui cp -r swagger-ui/dist ~/dev/x-auth-security/src/main/resources/public/docs i modified docs/index.html, deleting its header () element, as well as made its url dynamic. ... $(function () { var apiurl = window.location.protocol + "//" + window.location.host; if (window.location.pathname.indexof('/api') > 0) { apiurl += window.location.pathname.substring(0, window.location.pathname.indexof('/api')) } apiurl += "/api-docs"; log('api url: ' + apiurl); window.swaggerui = new swaggerui({ url: apiurl, dom_id: "swagger-ui-container", ... after making these changes, i was able to open fire up the app with "mvn spring-boot:run" and view http://localhost:8080/docs/index.html in my browser. 5. annotate your api. there are two services in x-auth-security: one for authentication and one for news. to provide more information to the "news" service's documentation, add @api and @apioperation annotations. these annotations aren't necessary to get a service to show up in swagger ui, but if you don't specify the @api("user"), you'll end up with an ugly-looking class name instead (e.g. example_xauth_userxauthtokencontroller). @restcontroller @api(value = "news", description = "news api") class newscontroller { map entries = new concurrenthashmap(); @requestmapping(value = "/news", method = requestmethod.get) @apioperation(value = "get news", notes = "returns news items") collection entries() { return this.entries.values(); } @requestmapping(value = "/news/{id}", method = requestmethod.delete) @apioperation(value = "delete news item", notes = "deletes news item by id") newsentry remove(@pathvariable long id) { return this.entries.remove(id); } @requestmapping(value = "/news/{id}", method = requestmethod.get) @apioperation(value = "get a news item", notes = "returns a news item") newsentry entry(@pathvariable long id) { return this.entries.get(id); } @requestmapping(value = "/news/{id}", method = requestmethod.post) @apioperation(value = "update news", notes = "updates a news item") newsentry update(@requestbody newsentry news) { this.entries.put(news.getid(), news); return news; } ... } you might notice the screenshot above only shows news. this is because swaggerconfig.default_include_patterns only specifies news. the following will include all apis. public static final list default_include_patterns = arrays.aslist("/.*"); after adding these annotations and modifying swaggerconfig , you should see all available services. in swagger-springmvc 0.8.x, the ability to use @apimodel and @apimodelproperty annotations was added. this means you can annotate newsentry to specify which fields are required. @apimodel("news entry") public static class newsentry { @apimodelproperty(value = "the id of the item", required = true) private long id; @apimodelproperty(value = "content", required = true) private string content; // getters and setters } this results in the model's documentation showing up in swagger ui. if "required" isn't specified, a property shows up as optional . parting thoughts the qa engineers and 3rd party ios developers have been very pleased with our api documentation. i believe this is largely due to swagger and its nice-looking ui. the swagger ui also provides an interface to test the endpoints by entering parameters (or json) into html forms and clicking buttons. this could benefit those qa folks that prefer using selenium to test html (vs. raw rest endpoints). i've been quite pleased with swagger-springmvc, so kudos to its developers. they've been very responsive in fixing issues i've reported . the only thing i'd like is support for recognizing jsr303 annotations (e.g. @notnull) as required fields. to see everything running locally, checkout my modified x-auth-security project on github and the associated commits for this article.
March 27, 2014
by Matt Raible
· 120,386 Views · 5 Likes
article thumbnail
Integration Testing for Spring Applications with JNDI Connection Pools
We all know we need to use connection pools where ever we connect to a database. All of the modern drivers using JDBC type 4 support it. In this post we will have look at an overview ofconnection pooling in spring applications and how to deal with same context in a non JEE enviorements (like tests). Most examples of connecting to database in spring is done using DriverManagerDataSource. If you don't read the documentation properly then you are going to miss a very important point. NOTE: This class is not an actual connection pool; it does not actually pool Connections. It just serves as simple replacement for a full-blown connection pool, implementing the same standard interface, but creating new Connections on every call. Useful for test or standalone environments outside of a J2EE container, either as a DataSource bean in a corresponding ApplicationContext or in conjunction with a simple JNDI environment. Pool-assuming Connection.close() calls will simply close the Connection, so any DataSource-aware persistence code should work. Yes, by default the spring applications does not use pooled connections. There are two ways to implement the connection pooling. Depending on who is managing the pool. If you are running in a JEE environment, then it is prefered use the container for it. In a non-JEE setup there are libraries which will help the application to manage the connection pools. Lets discuss them in bit detail below. 1. Server (Container) managed connection pool (Using JNDI) When the application connects to the database server, establishing the physical actual connection takes much more than the execution of the scripts. Connection pooling is a technique that was pioneered by database vendors to allow multiple clients to share a cached set of connection objects that provide access to a database resource. The JavaWorld article gives a good overview about this. In a J2EE container, it is recommended to use a JNDI DataSource provided by the container. Such a DataSource can be exposed as a DataSource bean in a Spring ApplicationContext via JndiObjectFactoryBean, for seamless switching to and from a local DataSource bean like this class. The below articles helped me in setting up the data source in JBoss AS. 1. DebaJava Post 2. JBoss Installation Guide 3. JBoss Wiki Next step is to use these connections created by the server from the application. As mentioned in the documentation you can use the JndiObjectFactoryBean for this. It is as simple as below If you want to write any tests using springs "SpringJUnit4ClassRunner" it can't load the context becuase the JNDI resource will not be available. For tests, you can then either set up a mock JNDI environment through Spring's SimpleNamingContextBuilder, or switch the bean definition to a local DataSource (which is simpler and thus recommended). As I was looking for a good solutions to this problem (I did not want a separate context for tests) this SO answer helped me. It sort of uses the various tips given in the Javadoc to good effect. The issue with the above solution is the repetition of code to create the JNDI connections. I have solved it using a customized runner SpringWithJNDIRunner. This class adds the JNDI capabilities to the SpringJUnit4ClassRunner. It reads the data source from "test-datasource.xml" file in the class path and binds it to the JNDI resource with name "java:/my-ds". After the execution of this code the JNDI resource is available for the spring container to consume. import javax.naming.NamingException; import org.junit.runners.model.InitializationError; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.mock.jndi.SimpleNamingContextBuilder; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * This class adds the JNDI capabilities to the SpringJUnit4ClassRunner. * @author mkadicha * */ public class SpringWithJNDIRunner extends SpringJUnit4ClassRunner { public static boolean isJNDIactive; /** * JNDI is activated with this constructor. * * @param klass * @throws InitializationError * @throws NamingException * @throws IllegalStateException */ public SpringWithJNDIRunner(Class klass) throws InitializationError, IllegalStateException, NamingException { super(klass); synchronized (SpringWithJNDIRunner.class) { if (!isJNDIactive) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "test-datasource.xml"); SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); builder.bind("java:/my-ds", applicationContext.getBean("dataSource")); builder.activate(); isJNDIactive = true; } } } } To use this runner you just need to use the annotation @RunWith(SpringWithJNDIRunner.class) in your test. This class extends SpringJUnit4ClassRunner beacuse a there can only be one class in the @RunWith annotation. The JNDI is created only once is a test cycle. This class provides a clean solution to the problem. 2. Application managed connection pool If you need a "real" connection pool outside of a J2EE container, consider Apache's Jakarta Commons DBCP or C3P0. Commons DBCP's BasicDataSource and C3P0's ComboPooledDataSource are full connection pool beans, supporting the same basic properties as this class plus specific settings (such as minimal/maximal pool size etc). Below user guides can help you configure this. 1. Spring Docs 2. C3P0 Userguide 3. DBCP Userguide The below articles speaks about the general guidelines and best practices in configuring the connection pools. 1. SO question on Spring JDBC Connection pools 2. Connection pool max size in MS SQL Server 2008 3. How to decide the max number of connections 4. Monitoring the number of active connections in SQL Server 2008 Note:- All the text in italics are copied from the spring documentation of the DriverManagerDataSource.
March 26, 2014
by Manu Pk
· 25,461 Views · 1 Like
article thumbnail
The Economics of Reuse
If you need the same functionality in two projects, you should reuse code between them, right? Or should you? For as long as there has been a profession of software engineering, we have tried to achieve more reuse. But reuse has both a benefit and a cost. Too often, the cost is forgotten. In this article, I examine the economics of reuse. True story: One of the earliest projects to embrace object-oriented programming in the 1990s did so with the goal of maximizing reuse. The team responsible for creating the company wide framework used the following formula for calculating the value of their work: [Value of reuse] = [numbers of uses of framework] * [value of the framework to reusers] – [cost of developing the framework] This formula is obviously correct, but this is where they went horribly wrong: The organization said [value of framework to reusers] = [cost of developing framework]. In other words: The more expensive it was to create, the more valuable it was to use. We have clearly progressed beyond this thinking. A more updated formula would say: [value of framework to reusers] = [cost of developing the feature in question]. But even this is too optimistic. No library comes for free to its users. At the very least, you have to discover the features and learn about the details. The cost of reusing depends on many factors, such as the quality of the framework and the documentation and also upon the type of feature. A complex algorithm with a simple interface is cheap to use, while most domain-specific frameworks require relatively much work to reuse. We can express this as a reuse value factor, likely between 90% and 50%. For most cases, my guess would be at about 75%. So we have: [value of reuse] = [number of users] * ([cost of feature] * [reuse cost factor]) – [cost of developing the reusable component] What about the other important factor: [cost of developing the reusable component]? It’s easy to assume that the cost of developing a feature in a framework is equal to that of developing the feature in an application, but on further analysis shows that this is far from true. A reusable component needs more documentation, it needs to handle more special cases and it has a slower feedback cycle. This cost is actually substantial and may mean that it costs between 150% to 300% or more to develop a feature for reuse. Personally, I think the reusability cost factor lies around 300%. And the lower this number, the higher the cost factor of reuse is likely to be, because that may mean we skimped on documentation etc. A revised number would be: [value of reuse] = [number of users] * ([cost of feature] * [reuse value factor]) – [reusability cost factor] * [cost of feature] Or [value of reuse] = [cost of feature] * ([number of users] * [reuse value factor] – [reusability cost factor]) The more complex formula actually lets us make a few predictions. Let’s say we assume a reuse value factor of 75 % (meaning that it requires 1/4 of the effort to reuse a library rather than creating the feature from scratch) and a reusability cost factor of 300 % (meaning that it requires three times the effort to create something that’s worth reusing). This means: [value of reuse] = [cost of feature] * ([number of users] * 75% – 300%) This equation breaks even when [number of users] = 4. That means that to get any value from your reused component, you better have five or more reusers or you have to find a way to substantially improve the [reuse value factor] or [reusability cost factor]. Very smart people have failed to do this. Improving the value: Increase the number of reusers: Simple enough, but when you do, you risk that the [reuse value factor] goes down as the framework doesn’t suit everybody equally well. Reduce the cost of reusing the library: This means investing in documentation, improving your design, improving testing to reduce the number of bugs, handle bug reports and feature requests faster from your reusers – all of which increase your cost reusability cost factor. Reduce the extra work in making the library reusable: The most important way to reduce the cost of developing for reuse is to choose the right kind of problem to solve. Problems with a small surface and big volume are best. That means: Easy to describe, hard to implement. Sadly, most of the juiciest fruit was picked years ago by the standard library in your programming language and by open source frameworks. On a global scale, reuse has saved the software industry tremendous amounts. In an organization, it can be hard to get the same effect. Reuse comes at a cost to the reuser and to the developer of the reusable library. How do you evaluate and improve your [reuse value factor] and your [reusability cost factor]?
March 24, 2014
by Johannes Brodwall
· 12,920 Views · 1 Like
article thumbnail
Clearing the Database with Django Commands
In a previous post, I presented a method of loading initial data into a Django database by using a custom management command. An accompanying task is cleaning the database up. Here I want to discuss a few options for doing that. First, some general design notes on Django management commands. If you run manage.py help you’ll see a whole bunch of commands starting with sql. These all share a common idiom – print SQL statements to the standard output. Almost all DB engines have means to pipe commands from the standard input, so this plays great with the Unix philosophy of building pipes of single-task programs. Django even provides a convenient shortcut for us to access the actual DB that’s being used with a given project – the dbshell command. As an example, we have the sqlflush command, which returns a list of the SQL statements required to return all tables in the database to the state they were in just after they were installed. In a simple blog-like application with "post" and "tag" models, it may return something like: $ python manage.py sqlflush BEGIN; DELETE FROM "auth_permission"; DELETE FROM "auth_group"; DELETE FROM "django_content_type"; DELETE FROM "django_session"; DELETE FROM "blogapp_tag"; DELETE FROM "auth_user_groups"; DELETE FROM "auth_group_permissions"; DELETE FROM "auth_user_user_permissions"; DELETE FROM "blogapp_post"; DELETE FROM "blogapp_post_tags"; DELETE FROM "auth_user"; DELETE FROM "django_admin_log"; COMMIT; Note there’s a lot of tables here, because the project also installed the admin and auth applications from django.contrib. We can actually execute these SQL statements, and thus wipe out all the DB tables in our database, by running: $ python manage.py sqlflush | python manage.py dbshell For this particular sequence, since it’s so useful, Django has a special built-in command named flush. But there’s a problem with running flush that may or may not bother you, depending on what your goals are. It wipes out all tables, and this means authentication data as well. So if you’ve created a default admin user when jump-starting the application, you’ll have to re-create it now. Perhaps there’s a more gentle way to delete just your app’s data, without messing with the other apps? Yes. In fact, I’m going to show a number of ways. First, let’s see what other existing management commands have to offer. sqlclear will emit the commands needed to drop all tables in a given app. For example: $ python manage.py sqlclear blogapp BEGIN; DROP TABLE "blogapp_tag"; DROP TABLE "blogapp_post"; DROP TABLE "blogapp_post_tags"; COMMIT; So we can use it to target a specific app, rather than using the kill-all approach of flush. There’s a catch, though. While flush runs delete to wipe all data from the tables, sqlclear removes the actual tables. So in order to be able to work with the database, these tables have to be re-created. Worry not, there’s a command for that: $ python manage.py sql blogapp BEGIN; CREATE TABLE "blogapp_post_tags" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "post_id" integer NOT NULL REFERENCES "blogapp_post" ("id"), "tag_id" varchar(50) NOT NULL REFERENCES "blogapp_tag" ("name"), UNIQUE ("post_id", "tag_id") ) ; CREATE TABLE "blogapp_post" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, <.......> ) ; CREATE TABLE "blogapp_tag" ( <.......> ) ; COMMIT; So here’s a first way to do a DB cleanup: pipe sqlclear appname into dbshell. Then pipe sql appname to dbshell. An alternative way, which I like less, is to take the subset of DELETE statements generated by sqlflush, save them in a text file, and pipe it through to dbshell when needed. For example, for the blog app discussed above, these statements should do it: BEGIN; DELETE FROM "blogapp_tag"; DELETE FROM "blogapp_post"; DELETE FROM "blogapp_post_tags"; DELETE COMMIT; The reason I don’t like it is that it forces you to have explicit table names stored somewhere, which is a duplication of the existing models. If you happen to change some of your foreign keys, for example, tables will need changing so this file will have to be regenerated. The approach I like best is more programmatic. Django’s model API is flexible and convenient, and we can just use it in a custom management command: from django.core.management.base import BaseCommand from blogapp.models import Post, Tag class Command(BaseCommand): def handle(self, *args, **options): Tag.objects.all().delete() Post.objects.all().delete() Save this code as blogapp/management/commands/clear_models.py, and now it can be invoked with: $ python manage.py clear_models
March 24, 2014
by Eli Bendersky
· 19,524 Views
article thumbnail
Spring Boot & JavaConfig integration
Java EE in general and Context and Dependency Injection has been part of the Vaadin ecosystem since ages. Recently, Spring Vaadin is a joint effort of the Vaadin and the Spring teams to bring the Spring framework into the Vaadin ecosystem, lead by Petter Holmström for Vaadin and Josh Long for Pivotal. Integration is based on the Spring Boot project - and its sub-modules, that aims to ease creating new Spring web projects. This article assumes the reader is familiar enough with Spring Boot. If not the case, please take some time to get to understand basic notions about the library. Note that at the time of this writing, there's no release for Spring Vaadin. You'll need to clone the project and build it yourself. The first step is to create the UI. In order to display usage of Spring's Dependency Injection, it should use a service dependency. Let's injection the UI through Constructor Injection to favor immutability. The only addition to a standard UI is to annotate it with org.vaadin.spring.@VaadinUI. @VaadinUI public class VaadinSpringExampleUi extends UI { private HelloService helloService; public VaadinSpringExampleUi(HelloService helloService) { this.helloService = helloService; } @Override protected void init(VaadinRequest vaadinRequest) { String hello = helloService.sayHello(); setContent(new Label(hello)); } } The second step is standard Spring Java configuration. Let's create two configuration classes, one for the main context and the other for the web one. Two thing of note: The method instantiating the previous UI has to be annotated with org.vaadin.spring.@UIScope in addition to standard Spring org.springframework.context.annotation.@Bean to bind the bean lifecycle to the new scope provided by the Spring Vaadin library. At the time of this writing, a RequestContextListener bean must be provided. In order to be compliant with future versions of the library, it's a good practice to annotate the instantiating method with @ConditionalOnMissingBean(RequestContextListener.class). @Configuration public class MainConfig { @Bean public HelloService helloService() { return new HelloService(); } } @Configuration public class WebConfig extends MainConfig { @Bean @ConditionalOnMissingBean(RequestContextListener.class) public RequestContextListener requestContextListener() { return new RequestContextListener(); } @Bean @UIScope public VaadinSpringExampleUi exampleUi() { return new VaadinSpringExampleUi(helloService()); } } The final step is to create a dedicated WebApplicationInitializer. Spring Boot already offers a concrete implementation, we just need to reference our previous configuration classes as well as those provided by Spring Vaadin, namely VaadinAutoConfiguration and VaadinConfiguration. public class ApplicationInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.showBanner(false) .sources(MainConfig.class) .sources(VaadinAutoConfiguration.class, VaadinConfiguration.class) .sources(WebConfig.class); } } At this point, we demonstrated a working Spring Vaadin sample application. Code for this article can be browsed and forked on Github.
March 10, 2014
by Nicolas Fränkel
· 13,606 Views
article thumbnail
Exporting Spring Data JPA Repositories as REST Services using Spring Data REST
Spring Data modules provides various modules to work with various types of datasources like RDBMS, NOSQL stores etc in unified way. In my previous article SpringMVC4 + Spring Data JPA + SpringSecurity configuration using JavaConfig I have explained how to configure Spring Data JPA using JavaConfig. Now in this post let us see how we can use Spring Data JPA repositories and export JPA entities as REST endpoints using Spring Data REST. First let us configure spring-data-jpa and spring-data-rest-webmvc dependencies in our pom.xml. org.springframework.data spring-data-jpa 1.5.0.RELEASE org.springframework.data spring-data-rest-webmvc 2.0.0.RELEASE Make sure you have latest released versions configured correctly, otherwise you will encounter the following error: java.lang.ClassNotFoundException: org.springframework.data.mapping.SimplePropertyHandler Create JPA entities. @Entity @Table(name = "USERS") public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_id") private Integer id; @Column(name = "username", nullable = false, unique = true, length = 50) private String userName; @Column(name = "password", nullable = false, length = 50) private String password; @Column(name = "firstname", nullable = false, length = 50) private String firstName; @Column(name = "lastname", length = 50) private String lastName; @Column(name = "email", nullable = false, unique = true, length = 50) private String email; @Temporal(TemporalType.DATE) private Date dob; private boolean enabled=true; @OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL) @JoinColumn(name="user_id") private Set roles = new HashSet<>(); @OneToMany(mappedBy = "user") private List contacts = new ArrayList<>(); //setters and getters } @Entity @Table(name = "ROLES") public class Role implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "role_id") private Integer id; @Column(name="role_name",nullable=false) private String roleName; //setters and getters } @Entity @Table(name = "CONTACTS") public class Contact implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "contact_id") private Integer id; @Column(name = "firstname", nullable = false, length = 50) private String firstName; @Column(name = "lastname", length = 50) private String lastName; @Column(name = "email", nullable = false, unique = true, length = 50) private String email; @Temporal(TemporalType.DATE) private Date dob; @ManyToOne @JoinColumn(name = "user_id") private User user; //setters and getters } Configure DispatcherServlet using AbstractAnnotationConfigDispatcherServletInitializer. Observe that we have added RepositoryRestMvcConfiguration.class to getServletConfigClasses() method. RepositoryRestMvcConfiguration is the one which does the heavy lifting of looking for Spring Data Repositories and exporting them as REST endpoints. package com.sivalabs.springdatarest.web.config; import javax.servlet.Filter; import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration; import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import com.sivalabs.springdatarest.config.AppConfig; public class SpringWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class[] getRootConfigClasses() { return new Class[] { AppConfig.class}; } @Override protected Class[] getServletConfigClasses() { return new Class[] { WebMvcConfig.class, RepositoryRestMvcConfiguration.class }; } @Override protected String[] getServletMappings() { return new String[] { "/rest/*" }; } @Override protected Filter[] getServletFilters() { return new Filter[]{ new OpenEntityManagerInViewFilter() }; } } Create Spring Data JPA repositories for JPA entities. public interface UserRepository extends JpaRepository { } public interface RoleRepository extends JpaRepository { } public interface ContactRepository extends JpaRepository { } That's it. Spring Data REST will take care of rest of the things. You can use spring Rest Shell https://github.com/spring-projects/rest-shell or Chrome's Postman Addon to test the exported REST services. D:\rest-shell-1.2.1.RELEASE\bin>rest-shell http://localhost:8080:> Now we can change the baseUri using baseUri command as follows: http://localhost:8080:>baseUri http://localhost:8080/spring-data-rest-demo/rest/ http://localhost:8080/spring-data-rest-demo/rest/> http://localhost:8080/spring-data-rest-demo/rest/>list rel href ====================================================================================== users http://localhost:8080/spring-data-rest-demo/rest/users{?page,size,sort} roles http://localhost:8080/spring-data-rest-demo/rest/roles{?page,size,sort} contacts http://localhost:8080/spring-data-rest-demo/rest/contacts{?page,size,sort} Note: It seems there is an issue with rest-shell when the DispatcherServlet url mapped to "/" and issue list command it responds with "No resources found". http://localhost:8080/spring-data-rest-demo/rest/>get users/ { "_links": { "self": { "href": "http://localhost:8080/spring-data-rest-demo/rest/users/{?page,size,sort}", "templated": true }, "search": { "href": "http://localhost:8080/spring-data-rest-demo/rest/users/search" } }, "_embedded": { "users": [ { "userName": "admin", "password": "admin", "firstName": "Administrator", "lastName": null, "email": "[email protected]", "dob": null, "enabled": true, "_links": { "self": { "href": "http://localhost:8080/spring-data-rest-demo/rest/users/1" }, "roles": { "href": "http://localhost:8080/spring-data-rest-demo/rest/users/1/roles" }, "contacts": { "href": "http://localhost:8080/spring-data-rest-demo/rest/users/1/contacts" } } }, { "userName": "siva", "password": "siva", "firstName": "Siva", "lastName": null, "email": "[email protected]", "dob": null, "enabled": true, "_links": { "self": { "href": "http://localhost:8080/spring-data-rest-demo/rest/users/2" }, "roles": { "href": "http://localhost:8080/spring-data-rest-demo/rest/users/2/roles" }, "contacts": { "href": "http://localhost:8080/spring-data-rest-demo/rest/users/2/contacts" } } } ] }, "page": { "size": 20, "totalElements": 2, "totalPages": 1, "number": 0 } } You can find the source code at https://github.com/sivaprasadreddy/sivalabs-blog-samples-code/tree/master/spring-data-rest-demo For more Info on Spring Rest Shell: https://github.com/spring-projects/rest-shell
March 7, 2014
by Siva Prasad Reddy Katamreddy
· 30,131 Views
article thumbnail
How to Install R Packages with Ansible
Here is a short snippet of Ansible playbook that installs R and any required packages to any nodes of the cluster: - name: Making sure R is installed apt: pkg=r-base state=installed - name: adding a few R packages command: /usr/bin/Rscript --slave --no-save --no-restore-history -e "if (! ('{{item}' %in% installed.packages()[,'Package'])) install.packages(pkgs={{item}, repos=c('http://www.freestatistics.org/cran/'))" with_items: - rjson - rPython - plyr - psych - reshape2 You should replace the repos with one chosen from the list of Cran mirrors. Note that the command above installs each package only if it is not already present, but messes up the “changed” status of Ansible’s PLAY RECAP by incorrectly reporting a change per R package at every run. Find more big data technical posts on my blog.
March 5, 2014
by Svend Vanderveken
· 6,253 Views
article thumbnail
Lessons Learned: ActiveMQ, Apache Camel and Connection Pooling
Every once in a while, I run into an interesting problem related to connections and pooling with ActiveMQ, and today I’d like to discuss something that is not always very clear and could potentially cause you to drink heavily when using ActiveMQ and Camel JMS. Not to say that you won’t want to drink heavily when using ActiveMQ and Camel anyway… in celebration of how delightful integration and messaging become when using them of course. So first up. Connection pooling. Sure, you’ve always heard to pool your connections. What does that really mean, and why do you want to do it? Opening up a connection to an ActiveMQ broker is a relativley expensive operation when compared to other actions like creating a session or consumer. So when sending or receiving messages and generally interacting with the broker, you’d like to reuse existing connections if possible. What you don’t want to do is rely on a JMS library (like Spring JmsTemplate for example) that opens and closes connections for each send or receive of a message… unless you can pool/cache your connections. So if we can agree that pooling connections is a good idea, take a look at an example config: You may even want to use Apache Camel and its wonderful camel-jms component because doing otherwise would just be silly. So maybe you want to set up a JMS config similar to so: This config basically means for consumers, set up 15 concurrent consumers, use transactions (local), use PERSISTENT messages for producers, set a timeout for 10000 for request-reply etc, etc. Huge note: If you want a more thorough taste of the configs for the jms component, especially around caching consumers, transactions and more, please take a look at Torsten’s excellent blog on Camel JMS with transactions – lesson learned. Maybe you should also spend some time poking around his blog as he’s got lots of good Camel/ActiveMQ stuff too Awesome so far. We have a connection pool of 10 connections, we will expect 10 sessions per connection (for a total of 100 sessions if we needed that…), and 15 concurrent consumers. We should be able to deal with some serious load, right? Take a look at this route here. It’s simple enough, exposes the activemq component (which will use the jmsConfig from above, so 15 concurrent consumers) and just does some logging: from("activemq:test.queue") .routeId("test.queue.routeId") .to("log:org.apache.camel.blog?groupSize=100"); Try and run this. You will find your consumers blocked up right away and stack traces will show this beauty: "Camel (camel-1) thread #1 - JmsConsumer[test.queue]" daemon prio=5 tid=7f81eb4bc000 nid=0x10abbb000 in Object.wait() [10abba000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <7f40e9070> (a org.apache.commons.pool.impl.GenericKeyedObjectPool$Latch) at java.lang.Object.wait(Object.java:485) at org.apache.commons.pool.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:1151) - locked <7f40e9070> (a org.apache.commons.pool.impl.GenericKeyedObjectPool$Latch) at org.apache.activemq.pool.ConnectionPool.createSession(ConnectionPool.java:146) at org.apache.activemq.pool.PooledConnection.createSession(PooledConnection.java:173) at org.springframework.jms.support.JmsAccessor.createSession(JmsAccessor.java:196) .... How can that possibly be? We have connection pooling… we have sessions per connection set to 10 per connection, so how are we all blocked up on creating new sessions? The answer is you’re exhausting the number of sessions, as you can expect by the stack trace. But how? And how much do I need to drink to resolve this? Well hold on now. Grab a beer and hear me out. First understand this. ActiveMQ’s pooling implementation uses commons-pool and the maxActiveSessionsPerConnection attribute is actually mapped to the maxActive property of the underlying pool. From the docs this means: maxActive controls the maximum number of objects (per key) that can allocated by the pool (checked out to client threads, or idle in the pool) at one time. The key here is “key” (literally… the ‘per key’ clause of the documentation). So in the ActiveMQ implementation the key is an object that represents 1) whether the session mode is transacted and 2) what the acknowledgement mode is () as seen here. So in plain terms, you’ll end up with a “maxActive” sessions for each key that’s used on that connection.. so if you have clients that use transactions, no transactions, client-ack, auto-ack, transacted-session, dups-okay, etc you can start to see that you’d end up with “maxActive” sessions for each permutation. So if you have maxActiveSesssionsPerConnection set to 10, you could really end up with 10 x 2 x 4 == 80 sessions. This is something to tuck away in the back of your mind. The second key here is that when the camel-jms component sets up consumers, it ends up sharing a single connection among all the consumers specified by the concurrentConsumers session. This is an interesting point, because camel-jms uses the underlying Spring framework’s DefaultMessageListenerContainer and unfortunately this restriction comes from that library. So if you have 15 concurrent consumers, they will all share a single connection (even if pooling… it will grab one connection from the pool and hold it). So if you have 15 consumers that each share a connection, each share a transacted mode, each share an ack mode, then you end up trying to create 15 sessions for that one connection. And you end up with the above. So my rule of thumb for avoiding these scenarios: Understand exactly what each of your producers and consumers are doing, what their TX and ACK modes are Always tune the max sessions param when you NEED to (too many session threads? i dunno..) but always do concurrentConsumers+1 as the value AT LEAST If producers and consumers are producing/consuming the same destination SPLIT UP THE CONNECTION POOL: one pool for consumers, one pool for producers Dunno how valuable this info will be, but I wanted to jot it down for myself. If someone else finds it valuable, or has questions, let me know in the comments.
March 4, 2014
by Christian Posta
· 26,568 Views · 2 Likes
article thumbnail
Custom Spring Namespaces Made Easier With JAXB
First of all, let me tell this out loud: Spring is no longer XML-heavy. As a matter of fact you can write Spring applications these days with minimal or no XML at all, using plenty of annotations, Java configuration and Spring Boot. Seriously stop ranting about Spring and XML, it's the thing the of the past. That being said you might still be using XML for couple of reasons: you are stuck with legacy code base, you chose XML for other reasons or you use Spring as a foundation for some framework/platform. The last case is actually quite common, for example Mule ESB and ActiveMQ use Spring underneath to wire up their dependencies. Moreover Spring XML is their way to configure the framework. However configuring message broker or enterprise service bus using plain Spring s would be cumbersome and verbose. Luckily Spring supports writing custom namespaces that can be embedded within standard Spring configuration files. These custom snippets of XML are preprocessed at runtime and can register many bean definitions at once in a concise and pleasantly looking (as far as XML allows) format. In a way custom namespaces are like macros that expand at runtime into multiple bean definitions. To give you a feeling of what are we aiming at, imagine a standard "enterprise" application that has several business entities. For each entity we define three, almost identical, beans: repository, service and controller. They are always wired in a similar way and only differ in small details. To begin with, our Spring XML looks like this (I am pasting screenshot with thumbnail to spare your eyes, it's huge and bloated): This is a "layered" architecture, thus we will call our custom namespace called onion - because onions have layers - and also because systems designed this way make me cry. By the end of this article you will learn how to collapse this pile of XML into: Look closely, it's still Spring XML file that is perfectly understandable by this framework - and you will learn how to achieve this. You can run arbitrary code for each top-level custom XML tag, e.g. single occurrence of registers repository, service and controller bean definitions all at once. The first thing to implement is writing a custom XML schema for our namespace. This is not that hard and will allow IntelliJ IDEA to show code completion in XML: Once the schema is completed we must register it in Spring using two files: /META-INF/spring.schemas: http\://nurkiewicz.blogspot.com/spring/onion/spring-onion.xsd=/com/blogspot/nurkiewicz/onion/ns/spring-onion.xsd /META-INF/spring.handlers: http\://nurkiewicz.blogspot.com/spring/onion/spring-onion.xsd=com.blogspot.nurkiewicz.onion.ns.OnionNamespaceHandler One maps schema URL into schema location locally, another points to so-called namespace handler. This class is fairly straightforward - it tells what to do with every top-level custom XML tag coming from this namespace encountered in Spring configuration file: import org.springframework.beans.factory.xml.NamespaceHandlerSupport; public class OnionNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("entity", new EntityBeanDefinitionParser()); registerBeanDefinitionParser("converter", new ConverterBeanDefinitionParser()); } } So, when piece of XML is found by Spring, it knows that our ConverterBeanDefinitionParser needs to be used. Remember that if our custom tag has children (like in the case of ), bean definition parser is called only for top-level tag. It is up to us how we parse and handle children. OK, so single tag is suppose to create the following two beans: The responsibility of bean definition parser is to programmatically register bean definitions otherwise defined in XML. I won't go into details of the API, but compare it with the XML snippet above, they match closely to each other: import org.w3c.dom.Element; public class ConverterBeanDefinitionParser extends AbstractBeanDefinitionParser { @Override protected AbstractBeanDefinition parseInternal(Element converterElement, ParserContext parserContext) { final String format = converterElement.getAttribute("format"); final String lenientStr = converterElement.getAttribute("lenient"); final boolean lenient = lenientStr != null? Boolean.valueOf(lenientStr) : true; final BeanDefinitionRegistry registry = parserContext.getRegistry(); final AbstractBeanDefinition converterBeanDef = converterBeanDef(format, lenient); registry.registerBeanDefinition(format + "Converter", converterBeanDef); final AbstractBeanDefinition readerBeanDef = readerBeanDef(format); registry.registerBeanDefinition(format + "Reader", readerBeanDef); return null; } private AbstractBeanDefinition readerBeanDef(String format) { return BeanDefinitionBuilder. rootBeanDefinition(ReaderFactoryBean.class). addPropertyValue("format", format). getBeanDefinition(); } private AbstractBeanDefinition converterBeanDef(String format, boolean lenient) { AbstractBeanDefinition converterBeanDef = BeanDefinitionBuilder. rootBeanDefinition(Converter.class.getName()). addConstructorArgValue(format + ".xml"). addConstructorArgValue(lenient). addPropertyReference("reader", format + "Reader"). getBeanDefinition(); converterBeanDef.setFactoryBeanName("convertersFactory"); converterBeanDef.setFactoryMethodName("build"); return converterBeanDef; } } Do you see how parseInternal() receives XML Element representing tag, extracts attributes and registers bean definitions? It's up to you how many beans you define in AbstractBeanDefinitionParser implementation. Just remember that we are barely constructing the configuration here, no instantiation took place yet. Once the XML file is fully parsed and all bean definition parsers triggered, Spring will start bootstrapping our application. One thing to keep in mind is returning null in the end. The API sort of expects you to return single bean definition. However no need to restrict ourselves, null is fine. The second custom tag that we support is that registers three beans at once. It's similar and thus not that interesting, see full source of EntityBeanDefinitionParser. One important implementation detail that can be found there is the usage of ManagedList. Documentation vaguely mentions it but it's quite valuable. If you want to define a list of beans to be injected knowing their IDs, a simple List is not sufficient, you must explicitly tell Spring you mean a list of bean references: List converterRefs = new ManagedList<>(); for (String converterName : converters) { converterRefs.add(new RuntimeBeanReference(converterName)); } return BeanDefinitionBuilder. rootBeanDefinition("com.blogspot.nurkiewicz.FooService"). addPropertyValue("converters", converterRefs). getBeanDefinition(); Using JAXB to simplify bean definition parsers OK, so by now you should be familiar with custom Spring namespaces and how they can help you. However they are quite low level by requiring you to parse custom tags using raw XML DOM API. However my team mate discovered that since we already have XSD schema file, why not use JAXB to handle XML parsing? First we ask maven to generate Java beans representing XML types and elements during build: org.jvnet.jaxb2.maven2 maven-jaxb22-plugin 0.8.3 xjc generate src/main/resources/com/blogspot/nurkiewicz/onion/ns com.blogspot.nurkiewicz.onion.ns.xml Under /target/generated-sources/xjc you will discover couple of Java files. I like generated JAXB models to have some commons prefix like Xml, which can be easily achieved with custom bindings.xjb file placed next to spring-onion.xsd: How does it change our custom bean definition parser? Previously we had this: final String clazz = entityElement.getAttribute("class"); //... final NodeList pageNodes = entityElement.getElementsByTagNameNS(NS, "page"); for (int i = 0; i < pageNodes.getLength(); ++i) { //...final String clazz = entityElement.getAttribute("class"); //... final NodeList pageNodes = entityElement.getElementsByTagNameNS(NS, "page"); for (int i = 0; i < pageNodes.getLength(); ++i) { //... Now we simply traverse Java beans: final XmlEntity entity = JaxbHelper.unmarshal(entityElement); final String clazz = entity.getClazz(); //... for (XmlPage page : entity.getPage()) { //... JaxbHelper is just a simple tool that hides checked exceptions and JAXB mechanics from outside: public class JaxbHelper { private static final Unmarshaller unmarshaller = create(); private static Unmarshaller create() { try { return JAXBContext.newInstance("com.blogspot.nurkiewicz.onion.ns.xml").createUnmarshaller(); } catch (JAXBException e) { throw Throwables.propagate(e); } } public static T unmarshal(Element elem) { try { return (T) unmarshaller.unmarshal(elem); } catch (JAXBException e) { throw Throwables.propagate(e); } } } Couple of words as a summary. First of all I don't encourage you to auto-generate repository/service/controller bean definitions for every entity. Actually it's a poor practice but the domain is familiar to all of us so I thought it will be a good example. Secondly, more important, custom XML namespaces are a powerful tool that should be used as a last resort when everything else fails, namely abstract beans, factory beans and Java configuration. Typically you'll want this kind of feature in frameworks or tools built in top of Spring. In that case check out full source code on GitHub.
February 26, 2014
by Tomasz Nurkiewicz
· 12,026 Views
article thumbnail
AngularJS IndexedDB Demo
over the past few months i've had a series of articles ( part 1 , part 2 , part 3 ) discussing indexeddb. in the last article i built a full, if rather simple, application that let you write notes. (i'm a sucker for note taking applications.) when i built the application, i intentionally did not use a framework. i tried to write nice, clear code of course, but i wanted to avoid anything that wasn't 100% necessary to demonstrate the application and indexeddb. in the perspective of an article, i think this was the right decision to make. i wanted my readers to focus on the feature and not anything else. but i thought this would be an excellent opportunity to try angularjs again. for the most part, this conversion worked perfectly. this may sound lame, but i found myself grinning as i built this application. i'm a firm believer that if something makes you happy then it is probably good for you. ;) i still find myself a bit... not confused... but slowed down by the module system and dependency injection. these are both things i grasp in general, but in angularjs they feel a bit awkward to me. it feels like something i'll never be able to code from memory, but will need to reference older applications to remind me. i'm not saying they are wrong of course, they just don't feel natural to me yet. on the flip side, the binding support is incredible. i love working with html templates and $scope. it feels incredibly powerful. heck, being able to add an input field and use it as a filter in approximately 30 seconds was mind blowing. one issue i ran into and i'm not convinced i created the best solution for was the async nature of indexeddb's database open logic. angularjs has a promises library built in and it works incredibly well for my application in general. but i needed the entire application to be bootstrapped to an async call for database startup. i got around that with two things that felt a bit like a hack. first, my home view (get all notes) ran a call to an init function to ensure the db was already open. so consider this init(): function init() { var deferred = $q.defer(); if(setup) { deferred.resolve(true); return deferred.promise; } var openrequest = window.indexeddb.open("indexeddb_angular",1); openrequest.onerror = function(e) { console.log("error opening db"); console.dir(e); deferred.reject(e.tostring()); }; openrequest.onupgradeneeded = function(e) { var thisdb = e.target.result; var objectstore; //create note os if(!thisdb.objectstorenames.contains("note")) { objectstore = thisdb.createobjectstore("note", { keypath: "id", autoincrement:true }); objectstore.createindex("titlelc", "titlelc", { unique: false }); objectstore.createindex("tags","tags", {unique:false,multientry:true}); } }; openrequest.onsuccess = function(e) { db = e.target.result; db.onerror = function(event) { // generic error handler for all errors targeted at this database's // requests! deferred.reject("database error: " + event.target.errorcode); }; setup=true; deferred.resolve(true); }; return deferred.promise; } this logic is similar to what i had in the non-framework app but i've made use of promises and a flag to remember when i've already opened the database. this lets me then tie to init() in my getnotes logic. function getnotes() { var deferred = $q.defer(); init().then(function() { var result = []; var handleresult = function(event) { var cursor = event.target.result; if (cursor) { result.push({key:cursor.key, title:cursor.value.title, updated:cursor.value.updated}); cursor.continue(); } }; var transaction = db.transaction(["note"], "readonly"); var objectstore = transaction.objectstore("note"); objectstore.opencursor().onsuccess = handleresult; transaction.oncomplete = function(event) { deferred.resolve(result); }; }); return deferred.promise; } all of this worked ok - but i ran into an issue on the other pages of my application. if for example you bookmarked the edit link for a note, you would run into an error. i could have applied the same fix in my service layer (run init first), but it just felt wrong. so instead i did this in my app.js: $rootscope.$on("$routechangestart", function(event,currentroute, previousroute){ if(!persistanceservice.ready() && $location.path() != '/home') { $location.path('/home'); }; }); the ready call was simply a wrapper to the flag variable. so yeah, this worked for me, but i still think there is (probably) a nicer solution. anyway, if you want to check it out, just hit the demo link below. i want to give a shoutout to sharon diorio for giving me a lot of help/tips/support while i built this app. p.s. i assume this is obvious, but i'm not really offering this up as a "best practices" angularjs application. i assume i could have done about every part better. ;)
February 25, 2014
by Raymond Camden
· 18,683 Views
article thumbnail
Brief comparison of BDD frameworks
JDave, Concordion, Easyb, JBehave, Cucumber are all compared here briefly for your convenience.
February 24, 2014
by Sebastian Laskawiec
· 130,068 Views · 16 Likes
  • Previous
  • ...
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • ...
  • 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
×