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

Events

View Events Video Library

The Latest Testing, Deployment, and Maintenance Topics

article thumbnail
Resource Injection vs. Dependency Injection Explained!
Fellow geeks, the following article provides an overview of injection in Java EE and describes the two injection mechanisms provided by the platform: Resource Injection and Dependency Injection. Java EE provides injection mechanisms that enable our objects to obtain the references to resources and other dependencies without having to instantiate them directly (explicitly with ‘new’ keyword). We simply declare the needed resources & other dependencies in our classes by drawing fields or methods with annotations that denotes the injection point to the compiler. The container then provides the required instances at runtime. The advantage of Injection is that it simplifies our code and decouples it from the implementations of its dependencies. Note should be given for the fact that Dependency Injection is a specification (also a design pattern) and Context and Dependency Injection (CDI) is an implementation andJava standard for DI. The following topics are discussed here: · Resource Injection · Dependency Injection · Difference between Context and Dependency Injection 1. Resource Injection One of the simplification features of Java EE is the implementation of basic Resource Injection to simplify web and EJB components. Resource injection enables you to inject any resource available in the JNDI namespace into any container-managed object, such as a servlet, an enterprise bean, or a managed bean. For eg, we can use resource injection to inject data sources, connectors, or any other desired resources available in the JNDI namespace. The type we’ll use for the reference to the instance happen to be injected is usually an interface, which would decouple our code from the implementation of the resource. For better understanding of the above statement let’s take a look at the example. The resource injection can be performed in the following three ways: · Field Injection · Method Injection · Class injection Now, the javax.annotation.Resource annotation is used to declare a reference to a resource. So before proceeding, let’s learn few elements of @Resource annotation. @Resource has the following elements: · name: The JNDI name of the resource · type: The Java type of the resource · authenticationType: The authentication type to use for the resource · shareable: Indicates whether the resource can be shared · mappedName: A non-portable, implementation-specific name to which the resource should be mapped · description: The description of the resource Thenameelement is the JNDI name of the resource, and is optional for field- and method-based injection. For field injection, d defaultnameis the field name. For method-based injection, the defaultnameis the JavaBeans property name based on the method. The‘name’ and ‘type’element must be specified for class injection. Thedescriptionelement is the description of the resource (optional). Let’s hop on to the example now. Field Injection: To use field-based resource injection, declare a field and annotate it with the @Resource annotation. The container will refer the name and type of the resource if the name and type elements are not specified. If you do specify the type element, it must match the field’s type declaration. package com.example; public class SomeClass { @Resource private javax.sql.DataSource myDB; ... } In the code above, the container infers the name of the resource based on the class name and the field name: com.example.SomeClass/myDB. The inferred type isjavax.sql.DataSource.class. package com.example; public class SomeClass { @Resource(name="customerDB") private javax.sql.DataSource myDB; ... } In the code above, the JNDI name is customerDB, and the inferred type is javax.sql.DataSource.class. Method Injection: To use method injection, declare a setter method and preceding with the @Resource annotation. The container will itself refer the name and type of the resource if in case it is not specified by programmer. The setter method must follow the JavaBeans conventions for property names: the method name must begin with set, have a void return type, and only one parameter (needless to say :P). Anyways, if you do specify the return type, it must match the field’s type declaration. package com.example; public class SomeClass { private javax.sql.DataSource myDB; ... @Resource private void setMyDB(javax.sql.DataSource ds) { myDB = ds; } ... } In the code above, the container refers the name of the resource according to the class name and the field name: com.example.SomeClass/myDB. The type which is javax.sql.DataSource.class. package com.example; public class SomeClass { private javax.sql.DataSource myDB; ... @Resource (name="customerDB") private void setMyDB (javax.sql.DataSource ds) { myDB = ds; } ... } In the code above, the JNDI name is customerDB, and the inferred type is javax.sql.DataSource.class. Class Injection: To use class-based injection, decorate the class with a @Resource annotation, and set the requiredname and type elements. @Resource(name="myMessageQueue", type="javax.jms.ConnectionFactory") public class SomeMessageBean { ... } Declaring Multiple Resources The @Resources annotation is used to group together multiple @Resource declarations for class injection only. @Resources({ @Resource(name="myMessageQueue", type="javax.jms.ConnectionFactory"), @Resource(name="myMailSession", type="javax.mail.Session") }) public class SomeMessageBean { ... } The code above shows the @Resources annotation containing two @Resource declarations. One is a JMS (Java Messagin Service) message queue, and the other is a JavaMail session. 2. Dependency Injection Dependency injection enables us to turn regular Java classes into managed objects and to inject them into any other managed object (objects wich are managed by the container). Using DI, our code can declare dependencies on any managed object. The container automatically provides instances of these dependencies at the injection points at runtime, n it also manages the lifecycle of these instances right from class loading to releasing it for Garbage Collection. Dependency injection in Java EE defines scopes. For eg, a managed object that is only happen to respond to a single client request (such as a currency converter) has a different scope than a managed object that is needed to process multiple client requests within a session (such as a shopping cart). We can define managed objects (also called managed beans) so that we can later inject by assigning a scope to a needed class: @javax.enterprise.context.RequestScoped public class CurrencyConverter { ... } Use the javax.inject.Inject annotation to inject managed beans; for example: public class MyServlet extends HttpServlet { @Inject CurrencyConverter cc; ... } Umlike resource injection, dependency injection is typesafe because it resolves by type. To decouple our code from the implementation of the managed bean, we can reference the injected instances using an interface type and have our managed bean (regular class controlled by container) implement that interface. I wouldn’t like to discuss more on DI or better saying CDI since we already have a great article published on this. 3. Difference between Resource Injection and Dependency Injection The differences between the RI and DI are listed below. 1. Resource Injection can inject JNDI Resources directly whereas Dependency Injection cannot. 2. Dependency Injection can inject Regular Classes (managed bean) directly whereas Resource Injection cannot. 3. Resource Injection resolves by resource name whereas Dependency Injectin resolves by type. 4. Dependency Injection is typesafe whereas Resoiurce Injection is not. Conclusion: Thus we learnt concept on types on Injection in Java EE and the differences between them. Just a brief. There’s more to come
February 2, 2015
by Lalit Rao
· 69,158 Views · 10 Likes
article thumbnail
We Can't Measure Programmer Productivity… or Can We?
If you go to Google and search for "measuring software developer productivity" you will find a whole lot of nothing. Seriously -- nothing. Nick Hodges, Measuring Developer Productivity By now we should all know that we don’t know how to measure programmer productivity. There is no clear cut way to measure which programmers are doing a better or faster job, or to compare productivity across teams. We “know” who the stars on a team are, who we can depend on to deliver, and who is struggling. And we know if a team is kicking ass – or dragging their asses. But how do we prove it? How can we quantify it? All sorts of stupid and evil things can happen when you try to measure programmer productivity. But let’s do it anyways. We’re Writing More Code, So We Must Be More Productive Developers are paid to write code. So why not measure how much code they write – how many lines of code get delivered? Because we've known since the 1980s that this is a lousy way to measure productivity. Lines of code can’t be compared across languages (of course), or even between programmers using the same language working in different frameworks or following different styles. Which is why Function Points were invented – an attempt to standardize and compare the size of work in different environments. Sounds good, but Function Points haven’t made it into the mainstream, and probably never will – very few people know how Function Points work, how to calculate them and how they should be used. The more fundamental problem is that measuring productivity by lines (or Function Points or other derivatives) typed doesn’t make any sense. A lot of important work in software development, the most important work, involves thinking and learning – not typing. The best programmers spend a lot of time understanding and solving hard problems, or helping other people understand and solve hard problems, instead of typing. They find ways to simplify code and eliminate duplication. And a lot of the code that they do write won’t count anyways, as they iterate through experiments and build prototypes and throw all of it away in order to get to an optimal solution. The flaws in these measures are obvious if we consider the ideal outcomes: the fewest lines of code possible in order to solve a problem, and the creation of simplified, common processes and customer interactions that reduce complexity in IT systems. Our most productive people are those that find ingenious ways to avoid writing any code at all. Jez Humble, The Lean Enterprise This is clearly one of those cases where size doesn’t matter. We’re Making (or Saving) More Money, so We Must Be Working Better We could try to measure productivity at a high level using profitability or financial return on what each team is delivering, or some other business measure such as how many customers are using the system – if developers are making more money for the business (or saving more money), they must be doing something right. Using financial measures seems like a good idea at the executive level, especially now that “every company is a software company”. These are organizational measures that developers should share in. But they are not effective – or fair – measures of developer productivity. There are too many business factors are outside of the development team’s control. Some products or services succeed even if the people delivering them are doing a lousy job, or fail even if the team did a great job. Focusing on cost savings in particular leads many managers to cut people and try “to do more with less” instead of investing in real productivity improvements. And as Martin Fowler points out there is a time lag, especially in large organizations – it can sometimes take months or years to see real financial results from an IT project, or from productivity improvements. We need to look somewhere else to find meaningful productivity metrics. We’re Going Faster, so We Must Be Getting More Productive Measuring speed of development – velocity in Agile – looks like another way to measure productivity at the team level. After all, the point of software development is to deliver working software. The faster that a team delivers, the better. But velocity (how much work, measured in story points or feature points or ideal days, that the team delivers in a period of time) is really a measure of predictability, not productivity. Velocity is intended to be used by a team to measure how much work they can take on, to calibrate their estimates and plan their work forward. Once a team’s velocity has stabilized, you can measure changes in velocity within the team as a relative measure of productivity. If the team’s velocity is decelerating, it could be an indicator of problems in the team or the project or the system. Or you can use velocity to measure the impact of process improvements, to see if training or new tools or new practices actually make the team’s work measurably faster. But you will have to account for changes in the team, as people join or leave. And you will have to remember that velocity is a measure that only makes sense within a team – that you can’t compare velocity between teams. Although this doesn't stop people from trying. Some shops use the idea of a well-known reference story that all teams in a program understand and use to base their story points estimates on. As long as teams aren't given much freedom on how they come up with estimates, and as long as the teams are working in the same project or program with the same constraints and assumptions, you might be able to do rough comparison of velocity between teams. But Mike Cohn warns that If teams feel the slightest indication that velocities will be compared between teams there will be gradual but consistent “point inflation.” ThoughtWorks explains that velocity <> productivity in their latest Technology Radar: We continue to see teams and organizations equating velocity with productivity. When properly used, velocity allows the incorporation of “yesterday's weather” into a team’s internal iteration planning process. The key here is that velocity is an internal measure for a team, it is just a capacity estimate for that given team at that given time. Organizations and managers who equate internal velocity with external productivity start to set targets for velocity, forgetting that what actually matters is working software in production. Treating velocity as productivity leads to unproductive team behaviors that optimize this metric at the expense of actual working software. Next: Just Stay Busy, Measure Outcomes, not Output; and more... Just Stay Busy One manager I know says that instead of trying to measure productivity “We just stay busy. If we’re busy working away like maniacs, we can look out for problems and bottlenecks and fix them and keep going”. In this case you would measure – and optimize for – cycle time, like in Lean manufacturing. Cycle time – turnaround time or change lead time, from when the business asks for something to when they get it in their hands and see it working – is something that the business cares about, and something that everyone can see and measure. And once you start looking closely, waste and delays will show up as you measure waiting/idle time, value-add vs. non-value-add work, and process cycle efficiency (total value-add time / total cycle time). “It’s not important to define productivity, or to measure it. It’s much more important to identify non-productive activities and drive them down to zero.” Erik Simmons, Intel Teams can use Kanban to monitor – and limit – work in progress and identify delays and bottlenecks. And Value Stream Mapping to understand the steps, queues, delays and information flows which need to be optimized. To be effective, you have to look at the end-to-end process from when requests are first made to when they are delivered and running, and optimize all along the path, not just the work in development. This may mean changing how the business prioritizes, how decisions are made and who makes the decisions. In almost every case we have seen, making one process block more efficient will have a minimal effect on the overall value stream. Since rework and wait times are some of the biggest contributors to overall delivery time, adopting “agile” processes within a single function (such as development) generally has little impact on the overall value stream, and hence on customer outcomes. Jezz Humble, The Lean Enterprise The down side of equating delivery speed with productivity? Optimizing for cycle time/speed of delivery by itself could lead to problems over the long term, because this incents people to think short term, and to cut corners and take on technical debt. We’re Writing Better Software, so We Must Be More Productive “The paradox is that when managers focus on productivity, long-term improvements are rarely made. On the other hand, when managers focus on quality, productivity improves continuously.” John Seddon, quoted in The Lean Enterprise We know that fixing bugs later costs more. Whether it’s 10x or 100+x, it doesn't really matter. And that projects with fewer bugs are delivered faster – at least up to a point of diminishing returns for safety-critical and life-critical systems. And we know that the costs of bugs and mistakes in software to the business can be significant. Not just development rework costs and maintenance and support costs. But direct costs to the business. Downtime. Security breaches. Lost IP. Lost customers. Fines. Lawsuits. Business failure. It’s easy to measure that you are writing good – or bad – software. Defect density. Defect escape rates (especially defects – including security vulnerabilities – that escape to production). Static analysis metrics on the code base, using tools like SonarQube. And we know how to write good software - or we should know by now. But is software quality enough to define productivity? Devops – Measuring and Improving IT Performance Devops teams who build/maintain and operate/support systems extend productivity from dev into ops. They measure productivity across two dimensions that we have already looked at: speed of delivery, and quality. But devops isn't limited to just building and delivering code – instead it looks at performance metrics for end-to-end IT service delivery: Delivery Throughput: deployment frequency and lead time, maximizing the flow of work into production Service Quality: change failure rate and MTTR It’s not a matter of just delivering software faster or better. It’s dev and ops working together to deliver services better and faster, striking a balance between moving too fast or trying to do too much at a time, and excessive bureaucracy and over-caution resulting in waste and delays. Dev and ops need to share responsibility and accountability for the outcome, and for measuring and improving productivity and quality. As I pointed out in an earlier post this makes operational metrics more important than developer metrics. According to recent studies, success in achieving these goals lead to improvements in business success: not just productivity, but market share and profitability. Measure Outcomes, not Output In The Lean Enterprise (which you can tell I just finished reading), Jez Jumble talks about the importance of measuring productivity by outcome – measuring things that matter to the organization – not output. “It doesn't matter how many stories we complete if we don’t achieve the business outcomes we set out to achieve in the form of program-level target conditions”. Stop trying to measure individual developer productivity. It’s a waste of time. Everyone knows who the top performers are. Point them in the right direction, and keep them happy. Everyone knows the people who are struggling. Get them the help that they need to succeed. Everyone knows who doesn't fit in. Move them out. Measuring and improving productivity at the team or (better) organization level will give you much more meaningful returns. When it comes to productivity: Measure things that matter – things that will make a difference to the team or to the organization. Measures that are clear, important, and that aren't easy to game. Use metrics for good, not for evil – to drive learning and improvement, not to compare output between teams or to rank people. I can see why measuring productivity is so seductive. If we could do it we could assess software much more easily and objectively than we can now. But false measures only make things worse. Martin Fowler, CannotMeasureProductivity
January 30, 2015
by Jim Bird
· 29,083 Views
article thumbnail
Git Flow and Immutable Build Artifacts
We love Git Flow. It’s awesome to have a standard release process where everybody is using the same terminology and tooling. It’s also great to have out-of-the-box answers to the same questions that get asked at the start of every project. For example: “How are we going to develop features in isolation?” “How are we going to separate release candidates from ongoing development?” “How are we going to deal with hotfixes?” Now it’s enough to just say ‘We use Git Flow’, and everybody’s on the same page. Well, mostly. Whilst Git Flow is terrific for managing features and separating release candidates from ongoing development, things get a little hazier when it comes time to actually release to production. This is because of a mismatch between the way that Git Flow works and another practice that is common in large development projects: immutable build artifacts. Immutable what? On most enterprise projects I work on these days, it’s considered a pretty good idea to progress exactly the same build artifact through testing, pre-production and into production. It doesn’t matter whether it’s a JAR file, WAR file, tar.gz file, or something more exotic – the key point is that you build it once, then deploy the same thing to each downstream environment. If you find a bug during this journey, you fix the bug, build a whole new artifact, and start the process again. In the absence of any established terminology, let’s just call these things immutable build artifacts. (Note that you’ll still need a separate, external file for those things that have to be different between environments, but by keeping the amount of stuff in that file to an absolute minimum, you’ll minimise your potential exposure to variances between environments.) Without immutable build artifacts, many development managers will start to sweat nervously. This is usually because at some stage in their careers they’ve been up at 2am in the morning prising apart build artifacts and trying to understand what changed between the pre-prod build (which worked just fine) and the current prod build (which is inexplicably failing). A bunch of things can cause this sort of problem. For example, it could be that somebody managed to sneak some change in between the two builds, or that some downstream build dependency changed between the two builds, or even that somebody tweaked the build process between the two builds. ‘That’ll never happen to me’, I hear you say, ‘if everybody follows our development methodology correctly’. And therein lies the problem: it’s difficult to absolutely guarantee that a developer won’t at the last minute do something stupid, like slip something into the wrong branch, upload an incorrectly-versioned downstream dependency, or mess with your buildbox configuration. My point is this: why open yourself up to the risk at all, when having a single artifact will eliminate a whole class of potential defects? Now for the actual problem A while back, I was working on a project using both Git Flow and immutable builds. A junior developer came to me looking confused. He was trying to understand when it would be OK for him to finish the current Git Flow release. The testers had just signed off on the current build. But if he finished the release, Git Flow was going to merge the release branch into master – and strictly speaking, he should create a new build from that. But if he created a new build, the testers were going to want to test it. If they found a problem, the fix was going to have to happen in a new release branch. But then when he closed that release, he was going to have to do a new build from master, which the testers would want to test again, right? And then, if they found a bug in that… I admired his highly conscientious approach to his work, but worried that his mind was going to disintegrate as it spun around this build-management paradox. I also had to acknowledge that he had stumbled head first into something that I had been wilfully ignoring in the hope that it would resolve itself; namely, the fundamental mismatch between Git Flow and the concept of immutable builds. Put simply, Git Flow works on the premise that production builds will only be done from the master branch. In contrast, immutable builds work on the premise that production builds will be done from either a release branch or a hotfix branch. There is no perfect way to work around this mismatch. The pragmatic solution Put bluntly, if you want truly immutable builds, then you should do them from the release or hotfix branch rather than master. However, because this runs contrary to how Git Flow works, there are a couple of important consequences to keep in mind. 1. Concurrent hotfixes and releases require special handling If you start and then finish a hotfix whilst a release branch is in process, then that hotfix’s changes won’t automatically be brought into the release branch by Git Flow. This means that a subsequent build from the release branch which goes into production won’t include the hotfix changes. Here’s a diagram illustrating the problem: Note that the inverse problem would apply if you tried to start a release whilst a hotfix was in progress. Thankfully, Git Flow will not let you have two release branches in progress at the same time, so we don’t have to worry about that particular possibility. (If you’re wondering how Git Flow avoids these scenarios in its regular usage, remember that it always merges back into master when a release or hotfix is finished, and that you’re supposed to always build from master. Consequently, if you’re building from master post-release or post-hotfix, you’ll always be getting the latest changes into the build.) The problem of concurrent hotfixes and releases can be solved by merging the hotfix branch into the release branch just before the hotfix branch gets finished (or vice-versa if you started a release whilst a hotfix was in progress). Here’s what it looks like: However, you will need to remember to do this merge manually because Git Flow won’t do it for you. 2. Version tags will be incorrect by default When you finish a release or hotfix, Git Flow merges the corresponding branch back into master, and then tags the resultant merge commit on master with the version number. However, because your immutable artifact will have been built from the release/hotfix branch, the commit SHA for the version tag in Git will be different from the SHA that the artifact was actually built from. Continuing on from our previous example: You may or may not care about this, for a number of reasons. Firstly, from the perspective of Git Flow, the merge commit on master should never have any changes in it. The only scenario that might lead to it having changes is if you have run concurrent hotfix and release branches (as described in the previous section) and forgotten to merge them prior to finishing. And you’llnever forget to do that now will you? :) Secondly, in the likely event that you are using some sort of continuous integration server to produce your builds, that server can probably associate its own number with each build, and stamp the resultant artifact with that number. The CI server will probably also have recorded the SHA that each build was done from. So from the artifact you could probably work backwards to the SHA that was used to produce it. If you’re nevertheless wary of the confusion that this backtracking process might introduce when trying to debug a production issue at 2am in the morning, you might still insist on having correct version tags. In that case the best thing I can think of is to manually create the tag on the release/hotfix branch yourself before finishing it and then, when finishing the release, run git flow [release/hotfix] finish with the -n option to stop it from trying to create the tag again (which would fail because the tag now already exists). I’m on a roll with my diagrams, so what the heck, let’s do one more: Wrapping Up On balance, I think the benefits of having immutable builds outweigh the costs of deviating from the Git Flow way of doing things. However, you do have to be aware of a couple of problematic scenarios. We’ll be experimenting in coming months with using Git Flow with our own immutable builds, and will let you know if anything else weird pops up. Who knows, perhaps we’ll even end up with our own version of Git Flow. Either way, I’d be interested in hearing from anybody else who has had the same problem.
January 30, 2015
by Ben Teese
· 11,050 Views · 1 Like
article thumbnail
Getting Started with Dropwizard: First Steps
Dropwizard is a bunch of superb frameworks glued together to provide a fast way of building web applications including REST APIs. We'll talk about great frameworks which are parts of Dropwizard as we go over our examples. The full code for the examples can be obtained here . The simplest way to create a Dropwizard project is to use the Maven archetype called java-simple which is a part of Dropwizard. This can be accomplished either via the command line or using your favorite IDE. Let's stick to the former approach. The command below is formatted for clarity but it should be pasted as a single line to the terminal. mvn archetype:generate -DgroupId=com.javaeeeee -DartifactId=DWGettingStarted -Dname=DWGettingStarted -Dpackage=com.javaeeeee.dwstart -DarchetypeGroupId=io.dropwizard.archetypes -DarchetypeArtifactId=java-simple -DinteractiveMode=false After the project was created it can be modified using an editor or opened in an IDE. All the three IntelliJ, Eclipse and Netbeans have Maven support. An important parameter to note in the pom.xml file of the newly created project is dropwizard.version, which at the time of writing was automatically set to 0.8.0-rc2-SNAPSHOT and the latest stable version was 0.7.1. We'll discuss later the important consequences of the version for project development. The directory structure of the project is shown below. There are multiple sub-packages and two classes that were created for us in a package com.javaeeeee.dwstart. Now let's create a simple resource class that produces a string “Hello world!”, start the application and test the results using both browser and cURL. The snippet below shows the resource class. @Path("/hello") public class HelloResource { @GET @Produces(MediaType.TEXT_PLAIN) public String getGreeting() { return "Hello world!"; } } There is a special package, com.javaeeeee.dwstart.recources for placing resource classes or an appropriate folder can be found from the screenshot above if you use a text editor and not an IDE. One of the main tenets of the REST architecture style is that each resource is assigned a URL. In our case the URL of our resource would be http://localhost:8080/hello, that is we access it from our local machine, the default port which is used by Dropwizard is 8080 and the final part of the URL is enshrined in @Path annotation in our class, in other words, the aforementioned annotation helps to describe the URL used to access a resource. Moving on to method getGreeting() it can be seen that it is a simple method which returns the desired string “Hello world!”, although it is marked with two annotations: first, @GET prescribes that this method is called when the aforementioned URL is accessed using HTTP GET method, second, annotation @Produces specifies what media types can be produced when the method is accessed by the client, such as browser, cURL or some other program. In our case it is plain text. These annotations are part of Java API for RESTful Web Services (JAX-RS), and its reference implementation Jersey is the cornerstone of Dropwizard. Other annotations include @POST for HTTP POST method, @DELETE for DELETE and so on and media types include MediaType.APPLICATION_JSON and not so popular MediaType.APPLICATION_XML among others. Now, to see the result of our coding, we should do some configuration. Let's open one of the created by Maven files, DWGettingStartedApplication.java, and register our resource. public void run(final DWGettingStartedConfiguration configuration, final Environment environment) { environment.jersey().register(new HelloResource()); } We added a single line environment.jersey().register(new HelloResource()); to help Dropwizard find our resource class. Now we have to create a jar-file which contains an embedded Jersey web server to serve the incoming requests, as well as all the necessary libraries. Dropwizard applications are packaged as executable jar-files rather than war-files which are deployed to an application server. The kind of jar files used by Dropwizard applications are also called “fat” because they include all the .class files necessary to run the application as this leads to a situation that the versions of all libraries are the same in both development and production environments which leads to less problems. One shouldn't worry about creating such jar-files as Maven creates them for us using instructions in the generated pom.xml file of the project. The jar-file can be created using command-line command issued from the project's folder mvn package or using an IDE. After that we should start the application, which could be accomplished either from the command line by issuing a command java -jar target/DWGettingStarted-1.0-SNAPSHOT.jar server or from the IDE which can be instructed to pass a “server” argument to the executable jar file. To stop the application it is sufficient to press Ctrl+C in the terminal. Now it is time to check if it works. The simplest way to achieve this is to navigate your browser to the URL mentioned earlier. You should see the greeting string in the main window of a browser. If you cannot see the greeting, there is probably some problems and the program’s output is the place to look for clues for what went wrong. The same greeting can be seen in the terminal window with help of cURL. curl -w "\n" localhost:8080/hello Protocol HTTP and GET method are defaults, so it is not necessary that they be included explicitly in the command. As the result a message "Hello world!" without quotes should be printed. The w-option is used to add a trailing newline to prettify the output. It is a good idea to start using tests as early as possible, so let's write a test that checks the work of our resource class using in-memory Jersey. We'll create the test in test packages and as we are testing a resource an appropriate package to place our test is com.javaeeeee.dwstart.resources (or src/test/com/javaeeeee/dwstart/resources folder). It is necessary that the following dependency be added to the pom-file of the project. (It works without explicit jUnit dependency.) io.dropwizard dropwizard-testing ${dropwizard.version} test An example test for our greeting resource is shown below. public class HelloResourceTest { @Rule public ResourceTestRule resource = ResourceTestRule.builder() .addResource(new HelloResource()).build(); @Test public void testGetGreeting() { String expected = "Hello world!"; //Obtain client from @Rule. Client client = resource.client(); //Get WebTarget from client using URI of root resource. WebTarget helloTarget = client.target("http://localhost:8080/hello"); //To invoke response we use Invocation.Builder //and specify the media type of representation asked from resource. Invocation.Builder builder = helloTarget.request(MediaType.TEXT_PLAIN); //Obtain response. Response response = builder.get(); //Do assertions. assertEquals(Response.Status.OK, response.getStatusInfo()); String actual = response.readEntity(String.class); assertEquals(expected, actual); } } The annotation @Rule is from jUnit realm and could be placed on public non-static fields and methods that return a value. This annotation may perform some initial setup and clean-up like @Before and @After methods, but it is more powerful as it allows to share functionality between classes and even projects. This rule is needed to allow us to access our resources from the code of the test using in-memory Jersey. At this point of time we should pause and discuss the version of our product. There is a pom.xml file in the dropwizard folder on the GitHub, which can readily be accessed by cloning the project, and this file specifies the version of constituent products among other things. It can be seen from it that the version of Jersey in the snapshot version of Dropwizard is 2.13 and in the version 0.7.1 it is 1.18.1. The version of Jersey influences the code of the tests as 1.x and 2.x versions of Jersey have different client APIs, that is the code to access the service programmatically from Java depends on the version of Jersey framework. Let's stick to the latest 2.x version of Jersey as it is liable to be included in following 0.8.x releases of Dropwizard and if you are interested how to test using the older version of Jersey client, please check the project repository , there is a special branch v0.7.x. Another observation concerning testing is that Fest matchers were superseded by AssertJ counterparts. First, we obtain an instance of Jersey client to make requests to our service. Second, we create an instance of a class that implements WebTarget interface for the resource using its URL. After that we use Invocation.Builder that helps to build request and send it to the server. The Invocation.Builder interface extends SynchInvoker interface which defines a bunch of get(...) methods used to invoke HTTP GET method synchronously. Finally, we check the results, namely that the HTTP status code was 200 and the desired string was returned. The same result could be obtained by chaining the methods as in the snippet below. actual = resource.client() .target("http://localhost:8080/hello") .request(MediaType.TEXT_PLAIN) .get(String.class); assertEquals(expected, actual); The replacement of the two assertions by a single is possible due to the fact that the get(...) method we used throws a WebApplicationException if the HTTP status code is not in the 2xx range, in other words if there is a problem. Now let's improve our resource to take a name and return a bespoke greeting. It could be done in a couple of ways using Jersey's annotations. The first is to use so-called path parameters, that is you pass the name using a URL like http://localhost:8080/hello/path_param/your_name. The application should return “Hello your_name”. Let's see a code snippet. @Path("/path_param/{name}") @GET @Produces(MediaType.TEXT_PLAIN) public String getNamedGreeting(@PathParam(value = "name") String name) { return "Hello " + name; } Now we see a @Path annotation on our method. It adds its content to those produced by class level annotation as seen from the URL. Methods marked with this annotation are called sub-resource methods. The name of the parameter, name, is in curly braces. Something interesting happens inside the parenthesis of the getNamedGreeting method. There is an annotation which prescribes to extract the content of the url after “/path_param/” to the method as a value. It should be noted that if you find yourself marking each method with the same annotation @Produces(MediaType.TEXT_PLAIN), the latter can be removed from methods and used to mark the class, then all the methods produce the desired media types, although this can be overruled by an annotations with a different media type for some of the methods. The second way to pass a name is to use query parameters and the URL could look like http://localhost:8080/hello/query_param?name=your_name. The output should be “Hello your_name” without quotes. The snippet is shown below. @Path("/query_param") @GET @Produces(MediaType.TEXT_PLAIN) public String getNamedStringWithParam(@DefaultValue("world") @QueryParam("name") String name) { return "Hello " + name; } Once again, the @Path annotation adds something to our URL, then the default value of the parameter is set in case there is no question mark and following it symbols in the URL using @DefaultValue annotation. In other words, if the parameter is omitted in the URL and it looks like http://localhost:8080/hello/query_param, a phrase “Hello world” is printed. The last annotation injects a parameter from the URL to the method's parameter. By the way, all these cases can be tested as was shown above. To test a method using query parameters one can use a queryParam(...) method of WebTarget interface. There is a couple of points to pay attention to. Firstly, there are other @*Param annotations available and secondly, the @DefaultValue annotation will not work with path parameters and to process the absence of the parameter a special sub-resource method should be introduced. You were patient enough to bear all this plain text staff, but it is not what REST APIs are about. Let's create another sub-resource method which is preprogrammed to return JSON representation. The first step is to create a representation class, which should be placed to com.javaeeeee.dwstart.core package. Let's limit ourselves to extremely simple example which is shown below. public class Greeting { @JsonProperty private String greeting; public Greeting() { } public Greeting(String greeting) { this.greeting = greeting; } public String getGreeting() { return greeting; } } The class above relies on one more important part of the Dropwizard stack namely Jackson , which can turn Java objects to JSON and vice versa. A @JsonProperty annotation is used to do the job. The sub-resource method looks like pretty much the same as our previously discussed methods. @Path("/hello_json") @GET @Produces(MediaType.APPLICATION_JSON) public Greeting getJSONGreeting() { return new Greeting("Hello world!"); } The difference is that we changed the media type and the method returns an instance of the greeting class. If you navigate your browser to to a URL http://localhost:8080/hello/hello_json or use cURL, you should see a JSON representation of the object {"greeting":"Hello world!"}. What if we remove the @Path annotation from the aforementioned method altogether? Well, if you try to access the localhost:8080/hello resource you'll see the text representation. How one could access the JSON-producing method? There is a special HTTP header called Accept which is used to instruct the server what representation to return, the process called content negotiation. The Jersey inside the Dropwizard will choose for us what method to use based on the content of the Accept header. Let's try cURL to do this. curl -w "\n" -H 'Accept: application/json' localhost:8080/hello/ The H-option is used to send headers and we instructed cURL to ask the JSON response. Other possible types to try could include text/plain and application/xml. The former should return the plain-text representation and the letter should result in error as there is no method in our resource class that can produce the latter media type response. Another way to engage in content negotiation is to use a REST client for your browser. There are several clients for each of major browsers but we will use Postman extension for Chrome browser. There are special fields to input headers as the screenshot below shows. One can enter the resource URL, headers and press Send button and the response will show up in the lower part of the window. To sum up we created a simple REST-like API using Dropwizard, which can greet its users. We learned how to create a Dropwizard project using Maven archetype and created a simple resource class to accomplish the task of greeting and a representation class to produce JSON response. An important ingredient of REST architecture style, HATEOAS, was omitted for now for simplicity reasons. Also a problem of testing resource classes was touched as well as the ways to access resources both from browser and command line. There are some other ideas for creating sub-resources such as returning the current date and adding two numbers using query parameters which can be easily implemented using the information presented in this article. References Dropwizard on GitHub Maven Archetypes Dropwizard Getting Started JAX-RS Resources and Subresources Dropwizard Testing Jersey Client API 2.x Jersey Client API 1.x Jackson annotations
January 30, 2015
by Dmitry Noranovich
· 35,662 Views · 3 Likes
article thumbnail
Grid with Images and Checkboxes in Android
Today I am going to discuss about creating a Grid in Android having image and associated checkbox. The idea is to have Grid with clickable images and checkbox. When an image is clicked the corresponding checkbox state is toggled. It is relatively easy to add custom items to the Grid. But its bit tricky to add clickable images and check/uncheck checkbox on click of the image. If you want to make the images clickable and check/uncheck the checkbox on image click, that is not that straightforward. In this article, I will take you through the creation of the Grid with clickable images and checkboxes. Creating a new project Open Eclipse and create a new android project. Choose a blank activity for the project. Create main Grid layout Open the layout file for the main activity and add a GridView component to it. Create Custom layout for grid items The next step is to create a custom layout that will be used to represent each item of the grid. Here we will define a custom layout using an ImageView and CheckBox android components. Create a new layout file named griditem.xml and add ImageView and CheckBox components to it as shown below: Adding Images to project For this sample project I am adding images to the project itself for use in the grid. But you can source those from database or any other content provider supported by android. In Android project there are few drawable-* folders under res folder. These are used for storing various resources used by the project. We can put images in any of these folders and Android SDK will copy them to other folders. If you have different images for different resolutions you can copy them to respective folders and correct image would be picked up based on the device resolution. Another option is to create a drawable folder under res and add images there. These will be copied to all drawable-* folders. We will use this approach here. Create custom adapter The next important step is to create a custom adapter which uses custom layout that we defined earlier to add items to the grid. The custom adapter should extend the BaseAdapter. The getView()method of the adapter is invoked for each item of the grid. In this method we assign values to the ImageView and checkbox. The listeners on the custom grid items are added here only. The code for getView() looks like the following: @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate( R.layout.griditems, null); holder.imageview = (ImageView) convertView.findViewById(R.id.grid_item_image); holder.checkbox = (CheckBox) convertView.findViewById(R.id.grid_item_checkbox); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.checkbox.setId(position); holder.imageview.setId(position); holder.checkbox.setOnClickListener(new OnClickListener() { public void onClick(View v) { CheckBox cb = (CheckBox) v; int id = cb.getId(); if (thumbnailsselection[id]){ //cb.setChecked(false); thumbnailsselection[id] = false; } else { //cb.setChecked(true); thumbnailsselection[id] = true; } } }); holder.imageview.setOnClickListener(new ImageClickListener(context, holder,thumbnailsselection)); holder.imageview.setImageResource(thumbnails[position]); holder.checkbox.setChecked(thumbnailsselection[position]); holder.id = position; return convertView; } Here we are saving the state of checkboxes in an array, thumbnailsselection. Since checkboxes are being added dynamically and there is no unique identifier for them, this will help in identifying the current state of checkbox whose state has to be toggled when an image is clicked. For the same reason we need to create a separate ImageClickListener. As we cannot identify the checkbox on click of corresponding image, we have to create the separate listener which holds the reference to holder class. Using this holder instance we can check/uncheck the checkbox when a corresponding image is clicked. Sometimes when you click on the image, the ImageClickListener is not invoked. The reason for this is that the checkbox overrides the focus event of container grid. Hence checkbox takes the focus when any item of the grid is clicked. To solve this issue you need to add the following properties to the checkbox. android:focusable=“false” android:focusableInTouchMode=“false” References Image icons source: http://www.iconarchive.com http://developer.android.com/
January 27, 2015
by Davinder Singla
· 22,257 Views
article thumbnail
The Cost of Laziness
Recently I had a dispute with my colleagues regarding performance penalty of lazy vals in Scala. It resulted in a set of microbenchmarks which compare lazy and non-lazy vals performance. All the sources can be found at http://git.io/g3WMzA. But before going to the benchmark results let's try to understand what can cause the performance penalty. For my JMH benchmark I created a very simple Scala class with lazy val in it: @State(Scope.Benchmark) class LazyValCounterProvider { lazy val counter = SlowInitializer.createCounter() } Now let's take a look at what is hidden under the hood of lazy keyword. At first, we need to compile given code with scalac, and then it can be decompiled to correspondent Java code. For this sake I used JD decompiler. It produced the following code: @State(Scope.Benchmark) @ScalaSignature(bytes="...") public class LazyValCounterProvider { private SlowInitializer.Counter counter; private volatile boolean bitmap$0; private SlowInitializer.Counter counter$lzycompute() { synchronized (this) { if (!this.bitmap$0) { this.counter = SlowInitializer.createCounter(); this.bitmap$0 = true; } return this.counter; } } public SlowInitializer.Counter counter() { return this.bitmap$0 ? this.counter : counter$lzycompute(); } } As it's seen, the lazy keyword is translated to a classical double-checked locking idiom for delayed initialization. Thus, most of the time the only performance penalty may come from a single volatile read per lazy val read (except for the time it takes to initialize lazy val instance since its very first usage). Let's finally measure its impact in numbers. My JMH-based microbenchmark is as simple as: public class LazyValsBenchmarks { @Benchmark public long baseline(ValCounterProvider eagerProvider) { return eagerProvider.counter().incrementAndGet(); } @Benchmark public long lazyValCounter(LazyValCounterProvider provider) { return provider.counter().incrementAndGet(); } } A baseline method access a final counter object and increments an integer value by 1 by calling incrementAndGet . And as we've just found out, the main benchmark method - lazyValCounter - in addition to what baseline method does also does one volatile read. Note: all measurements are performed on MBA with Core i5 1.7GHz CPU. All results were obtained by running JMH in a throughput mode. Both score and score error columns show operations/second. Each JMH run made 10 iterations and took 50 seconds. I performed 6 measurements with the different JVM and JMH options: client VM, 1 thread Benchmark Score Score error baseline 412277751.619 8116731.382 lazyValCounter 352209296.485 6695318.185 client VM, 2 threads Benchmark Score Score error baseline 542605885.932 15340285.497 lazyValCounter 383013643.710 53639006.105 client VM, 4 threads Benchmark Score Score error baseline 551105008.767 5085834.663 lazyValCounter 394175424.898 3890422.327 server VM, 1 thread Benchmark Score Score error baseline 407010942.139 9004641.910 lazyValCounter 341478430.115 18183144.277 server VM, 2 threads Benchmark Score Score error baseline 531472448.578 22779859.685 lazyValCounter 428898429.124 24720626.198 server VM, 4 threads Benchmark Score Score error baseline 549568334.970 12690164.639 lazyValCounter 374460712.017 17742852.788 The numbers show that lazy vals performance penalty is quite small and can be ignored in practice. For further reading about the subject I would recommend SIP 20 - Improved Lazy Vals Initialization, which contains very interesting in-depth analysis of existing issues with lazy initialization implementation in Scala.
January 26, 2015
by Roman Gorodyshcher
· 11,826 Views · 1 Like
article thumbnail
Reducing Test Times by Only Running Impacted Tests
This article follows on from my Omnipresent, Infallible, Omnipotent and Instantaneous Build Technologies one a couple of day ago. Specifically the last section: “Minimalist test execution, via hacks”, that addressed test times being very lengthy. I’ve made a proof of concept of that for Maven. The tests impacted by a change (a pending change specifically) can now be quickly determined and fed into the test runner to massively reduce test times. Massively reduced, this is, if you’ve managed to engineer hours of Selenium tests. Proof of concept I forked a Github project that Petri Kainulainen had made to discuss coverage for a Maven projects. Clone my fork, but cd into the “code-coverage-jacoco” directory. Running testimpact.sh there – it will rebuild a map of what tests cover what production-classes (sources). I’ve checked in the previous results from running this script, that’s what a team would do. It runs Maven against one test at a time, to calculate coverage then store that per test. Actually for Petri’s example, I’m only focussing on the integration tests (run by the “failsafe” plugin) rather than the unit tests (run by the “surefire” plugin). Even though Petri’s example project is not launching Selenium (or equivalent slow test), the integration test phase is where you would run that for a canonical Maven project. The testimpact.sh script uses python and ack (you’ll have to install those if you want to run this). I tried to use sqlite3’s CSV ingesting, but it was impossibly opaque, even with using StackOverflow’s best Questions/Answers, so I flipped to Python. Petri’s example uses JaCoCo for coverage, which spits out a handy CSV report (as well as HTML). There are some text files in src/integration-test/meta/ccexample that show the sources covered by each test. Yes, they are checked in. Those files end in .java but are actually plain text (sorry): There’s another file src/integration-test/impact-map.txt that contains a list of production sources and the tests that would exercise them. Actually its a map of sources vs tests: Experimenting with what I’ve done Change one of the two production classes in src/main/java/ccexample. Yes they are clones of each other – that’s just something I did after forking to increase the class count at the start. Don’t commit that pending change, just leave it there showing up as modified in git status. Run python tests.py and watch it run one or two tests in the same invocation. Now undo that change, and change the other source file, and run python tests.py again. Different tests ran, right? Undo that change, and do python tests.py once more. No tests ran, right? That would be the same for changed sources/classes that had no tests exercising them (covering them under test invocation) at all. Of course these few tests are really quick, but they could have been three subset from hundreds or thousands of tests with an elapsed time of many hours. Turning the idea into a solution It is also worth noting that scripts as I have them are not robust or optimized. There’s more source-control systems than just Git, of course. The script needs to be able to work for a commit too, not just a pending commit. The storage format for impact-map.txt will not scale, and you might want to excise certain categories of POJO if every test exercises them. To be correct in Maven-land, this should be a bunch of plugins that fit the Maven style. One plugin would be invoked from Jenkins and would probably run constantly if corresponding test times are up in the hours. That Jenkins job should check in changes to the meta-files as it sees changes. This is benign, and useful to team members who may want the shorter build. Would you check the impact map into source-control? It seems to me that the map data is related to the other source files. Perhaps if you took a historical view to things, the impact maps change with the source code at the same time. If you were bug-fixing something from the past (checking out a prior revision), you might be happy that the impact map also goes back in time. Of course there’s nothing here that couldn’t be stored in a key/value store, including the changing map over time. Or a service that could answer the question “what tests should I run if these source files are changed?” Except perhaps that uncommitted work (on your own workstation) isn’t going to be present in that store until after a commit, and the impact map data us updated to that into account. Taking the idea even further I’ve suggested that Selenium is the technology that would greatly lengthen test times. There are many other test technologies that are one, two or three orders slower than perfect unit tests. This idea is applicable to much more than just Selenium – the only requirement is to be able to measure coverage while individual tests are running. What I have done could also be extended to the “surefire” phase – almost identical to what I’ve done already – an opportunity for reuse of course. CI daemons like Jenkins could benefit from the same impact-driven test time reduction. At least the per-commit jobs that we do for the Continuous Delivery era of enterprise development. This idea could be extended to the test-method level. That would be harder still, but achievable in the same way. It comes with arguably negligible gains, though. You’d code it all, and work out that 5% wasn’t worth it (versus other ways of speeding up tests). We’d need Intellij and Eclipse plugins for this. The script needs to be able to work for range of commits as many teams batch them in in Jenkins-land. I wonder what is out there that already does this sort of thing already. Followups (Jan 13, 17, 2015) Markus Kohler notes: This is a great idea and I guess similar to what Google does (there was blog post about it, can’t find it ATM). But I think as it is it would not be completely correct. The reason is that as far as I can see, you just run the tests that use the modified class files. That is not enough, because in Java changing one source code file might result in other files needed to be recompiled. Gradle’s Java plugin (http://www.gradle.org/docs/current/userguide/java_plugin.html) computes that set of files for example for incremental compilation. As an example if a final static String is changed and that String is used in other classes, these classes has to be recompiled because the Java compiler inlines these kind of strings. Any Test that uses these classes would have to be re-run. He’s quite right there’s room for some edge case mistakes. To overcome those, you would need to check for changes that would lead to final static fields being inlined into other classes. Maybe a list of source files that, if changed, would cause all tests to be re-run (after a suitable warning).
January 25, 2015
by Paul Hammant
· 11,490 Views
article thumbnail
Mule ESB in Docker
In this article I will attempt to run the Mule ESB community edition in Docker in order to see whether it is feasible without any greater inconvenience. My goal is to be able to use Docker both when testing as well as in a production environment in order to gain better control over the environment and to separate different types of environments. I imagine that most of the Docker-related information can be applied to other applications – I have used Mule since it is what I usually work with. The conclusion I have made after having completed my experiments is that it is possible to run Mule ESB in Docker without any inconvenience. In addition, Docker will indeed allow me to have better control over the different environments and also allow me to separate them as I find appropriate. Finally, I just want to mention that I have used Docker in an Ubuntu environment. I have not attempted any of the exercises in Docker running on Windows or Mac OS X. Docker Briefly In short, Docker allows for creating of images that serve as blueprints for containers. A Docker container is an instance of a Docker image in the same way a Java object is an instance of a Java class. FROM codingtony/java MAINTAINER tony(dot)bussieres(at)ticksmith(dot)com RUN wget https://repository.mulesoft.org/nexus/content/repositories/releases/org/mule/distributions/mule-standalone/3.5.0/mule-standalone-3.5.0.tar.gz RUN cd /opt && tar xvzf ~/mule-standalone-3.5.0.tar.gz RUN echo "4a94356f7401ac8be30a992a414ca9b9 /mule-standalone-3.5.0.tar.gz" | md5sum -c RUN rm ~/mule-standalone-3.5.0.tar.gz RUN ln -s /opt/mule-standalone-3.5.0 /opt/mule CMD [ "/opt/mule/bin/mule" ] The resource isolation features of Linux are used to create Docker containers, which are more lightweight than virtual machines and are separated from the environment in which Docker runs, the host. Using Docker an image can be created that, every time it is started has a known state. In order to remove any doubts about whether the environment has been altered in any way, the container can be stopped and a new container started. I can even run multiple Docker containers on one and the same computer to simulate a multi-server production environment. Applications can also be run in their own Docker containers, as shown in this figure. Three Docker containers, each containing a specific application, running in one host. A more detailed introduction to Docker is available here. The main entry point to the Docker documentation can be found here. Motivation Some of the motivations I have for using Docker in both testing and production environments are: The environment in which I test my application should be as similar as the final deployment environment as possible, if not identical. Making the deployment environment easy to scale up and down. If it is easy to start a new processing node when need arise and stop it if it is no longer used, I will be able to adapt to changes rather quickly and thus reduce errors caused by, for instance, load peaks. Maintain an increased number of nodes to which applications can be deployed. Instead of running one instance of some kind of application server, Mule ESB in my case, on a computer, I want multiple instances that are partitioned, for instance, according to importance. High-priority applications run on one separate instance, which have higher priority both as far as resources (CPU, memory, disk etc) are concerned but also as far as support is concerned. Applications which are less critical run on another instance. Enable quick replacement of instances in the deployment environment. Reasons for having to replace instances may be hardware failure etc. Better control over the contents of the different environments. The concept of an environment that, at any time, may be disposed (and restarted) discourages hacks in the environment, which are usually poorly documented and sometimes difficult to trace. Using Docker, I need to change the appropriate Docker image if I want to make changes to some application environment. The Docker image file, commonly known as Dockerfile, can be checked into any ordinary revision control system, such as Git, Subversion etc, making changes reversible and traceable. Automate the creation of a testing environment. An example could be a nightly job that runs on my build server which creates a test environment, deploys one or more applications to it and then performs tests, such as load-testing. Prerequisites To get the best possible experience when running Docker, I run it under Ubuntu. According to the current documentation, Docker is supported under the following versions of Ubuntu: 12.04 LTS (64-bit) 13.04 (64-bit) 13.10 (64-bit) 14.04 (64-bit) Against my usual conservative self, I chose Ubuntu 14.10, which at the time of writing this article is the latest version. While I haven’t run into any issues, I cannot promise anything regarding compatibility with Docker as far as this version of Ubuntu is concerned. Installing Docker Before we install anything, those who have the Docker version from the Ubuntu repository should remove this version before installing a newer version of Docker, since the Ubuntu repository does not contain the most recent version and the package does not have the same name as the Docker package we will install: sudo apt-get remove docker.io The simplest way to install Docker is to use an installation script made available at the Docker website: curl -sSL https://get.docker.com/ubuntu/ | sudo sh If you are not running Ubuntu or if you do not want to use the above way of installing Docker, please refer to this page containing instructions on how to install Docker on various platforms. To verify the Docker installation, open a terminal window and enter: sudo docker version Output similar to the following should appear: Client version: 1.4.1 Client API version: 1.16 Go version (client): go1.3.3 Git commit (client): 5bc2ff8 OS/Arch (client): linux/amd64 Server version: 1.4.1 Server API version: 1.16 Go version (server): go1.3.3 Git commit (server): 5bc2ff8 We are now ready to start a Mule instance in Docker. Running Mule in Docker One of the advantages with Docker is that there is a large repository of Docker images that are ready to be used, and even extended if one so wishes. ThisDocker image is the one that I will use in this article. It is well documented, there is a source repository and it contains a recent version of the Mule ESB Community Edition. Some additional details on the Docker image: Ubuntu 14.04. Oracle JavaSE 1.7.0_65. This version will change as the PPA containing the package is updated. Mule ESB CE 3.5.0 Note that the image may change at any time and the specifications above may have changed. If you intend to use Docker in your organization, I would suspect that the best alternative is to create your own Docker images that are totally under your control. The Docker image repository is an excellent source of inspiration and aid even in this case. Starting a Docker Container To start a Docker container using this image, open a terminal window and write: sudo docker run codingtony/mule The first time an image is used it needs to be downloaded and created. This usually takes quite some time, so I suggest a short break here – perhaps for a cup of coffee or tea. If you just want to download an image without starting it, exchange the Docker command “run” with “pull”. Once the container is started, you will see some output to the console. If you are familiar with Mule, you will recognize the log output: MULE_HOME is set to /opt/mule-standalone-3.5.0 Running in console (foreground) mode by default, use Ctrl-C to exit... MULE_HOME is set to /opt/mule-standalone-3.5.0 Running Mule... --> Wrapper Started as Console Launching a JVM... Starting the Mule Container... Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved. INFO 2015-01-05 04:41:42,302 [WrapperListener_start_runner] org.mule.module.launcher.MuleContainer: ********************************************************************** * Mule ESB and Integration Platform * * Version: 3.5.0 Build: ff1df1f3 * * MuleSoft, Inc. * * For more information go to http://www.mulesoft.org * * * * Server started: 1/5/15 4:41 AM * * JDK: 1.7.0_65 (mixed mode) * * OS: Linux (3.16.0-28-generic, amd64) * * Host: f95698cfb796 (172.17.0.2) * ********************************************************************** Note that: In the text-box containing information about the Mule ESB and Integration Platform, there is a row which starts with “Host:”. The hexadecimal digit that follows is the Docker container id and the IP-address is the external IP-address of the Docker container in which Mule is running. Before we do anything with the Mule instance running in Docker, let’s take a look at Docker containers. Docker Containers We can verify that there is a Docker container running by opening another terminal window, or a tab in the first terminal window, and running the command: sudo docker ps As a result, you will see output similar to the following (I have edited the output in order for the columns to be aligned with the column titles): CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f95698cfb796 codingtony/mule:latest "/opt/mule/bin/mule" 7 min ago Up 7 min jolly_hopper From this output we can see that: The ID of the container is f95698cfb796. This ID can be used when performing operations on the container, such as stopping it, restarting it etc. The name of the image used to created the container. The command that is currently executing. If we look at the Dockerfile for the image, we can see that the last line in this file is: CMD [ “/opt/mule/bin/mule” ] This is the command that is executed whenever an instance of the Docker image is launched and it matches what we see in the COMMAND column for the Docker container. The CREATED column shows how much time has passed since the container was created. The STATUS column shows the current status of the image. When you have used Docker for a while, you can view all the containers using: sudo docker ps -a This will show you containers that are not running, in addition to the running ones. Containers that are not running can be restarted. The PORTS column shows any port mappings for the container. More about port mappings later. Finally, the NAMES column contain a more human-friendly container name. This container name can be used in the same way as the container id. Docker containers will consume disk-space and if you want to determine how much disk-space each of the containers on your computer use, issue the following command: sudo docker ps -a -s An additional column, SIZE, will be shown and in this column I see that my Mule container consumes 41,76kB. Note that this is in addition to the disk-space consumed by the Docker image. This number will grow if you use the container under a longer period of time, as the container retains any files written to disk. To completely remove a stopped Docker container, find the id or name of the container and use the command: sudo docker rm [container id or name here] Before going further, let’s stop the running container and remove it: sudo docker stop [container id or name here] sudo docker rm [container id or name here] Files and Docker Containers So far we have managed to start a Mule instance running inside a Docker container, but there were no Mule applications deployed to it and the logs that were generated were only visible in the terminal window. I want to be able to deploy my applications to the Mule instance and examine the logs in a convenient way. In this section I will show how to: Share one or more directories in the host file-system with a Docker container. Access the files in a Docker container from the host. As the first step in looking at sharing directories between the host operating system and a Docker container, we are going to look at Mule logs. As part of this exercise we also set up the directories in the host operating system that are going to be shared with the Docker container. In your home directory, create a directory named “mule-root”. In the “mule-root” directory, create three directories named “apps”, “conf” and “logs”. Download the Mule CE 3.5.0 standalone distribution from this link. From the Mule CE 3.5.0 distribution, copy the files in the “apps” directory to the “mule-root/apps” directory you just created. From the Mule CE 3.5.0 distribution, copy the files in the “conf” directory to the “mule-root/conf” directory you created. The resulting file- and directory-structure should look like this (shown using the tree command): ~/mule-root/ ├── apps │ └── default │ └── mule-config.xml ├── conf │ ├── log4j.properties │ ├── tls-default.conf │ ├── tls-fips140-2.conf │ ├── wrapper-additional.conf │ └── wrapper.conf └── logs Edit the log4j.properties file in the “mule-root/conf” directory and set the log-level on the last line in the file to “DEBUG”. This modification has nothing to do with sharing directories, but is in order for us to be able to see some more output from Mule when we run it later. The last two lines should now look like this: # Mule classes log4j.logger.org.mule=DEBUG Binding Volumes We are now ready to launch a new Docker container and when we do, we will tell Docker to map three directories in the Docker container to three directories in the host operating system. Three directories in a Docker container bound to three directories in the host. Launch the Docker container with the command below. The -v option tells Docker that we want to make the contents of a directory in the host available at a certain path in the Docker container file-system. The -d option runs the container in the background and the terminal prompt will be available as soon as the id of the newly launched Docker container has been printed. sudo docker run -d -v ~/mule-root/apps:/opt/mule/apps -v ~/mule-root/conf:/opt/mule/conf -v ~/mule-root/logs:/opt/mule/logs codingtony/mule Examine the “mule-root” directory and its subdirectories in the host, which should now look like below. The files on the highlighted rows have been created by Mule. mule-root/ ├── apps │ ├── default │ │ └── mule-config.xml │ └── default-anchor.txt ├── conf │ ├── log4j.properties │ ├── tls-default.conf │ ├── tls-fips140-2.conf │ ├── wrapper-additional.conf │ └── wrapper.conf └── logs ├── mule-app-default.log ├── mule-domain-default.log └── mule.log Examine the “mule.log” file using the command “tail -f ~/mule-root/logs/mule.log”. There should be periodic output written to the log file similar to the following: DEBUG 2015-01-05 12:05:37,216 [Mule.app.deployer.monitor.1.thread.1] org.mule.module.launcher.DeploymentDirectoryWatcher: Checking for changes... DEBUG 2015-01-05 12:05:37,216 [Mule.app.deployer.monitor.1.thread.1] org.mule.module.launcher.DeploymentDirectoryWatcher: Current anchors: default-anchor.txt DEBUG 2015-01-05 12:05:37,216 [Mule.app.deployer.monitor.1.thread.1] org.mule.module.launcher.DeploymentDirectoryWatcher: Deleted anchors: Stop and remove the container: sudo docker stop [container id or name here] sudo docker rm [container id or name here] Direct Access to Docker Container Files When running Docker under the Ubuntu OS it is also possible to access the file-system of a Docker container from the host file-system. It may be possible to do this under other operating systems too, but I haven’t had the opportunity to test this. This technique may come in handy during development or testing with Docker containers for which you haven’t bound any volumes. Note! If given the choice to use either volume binding, as seen above, or direct access to container files as we will look at in this section for something more than a temporary file access, I would chose to use volume binding. Direct access to Docker container files relies on implementation details that I suspect may change in future versions of Docker if the developers find it suitable. With all that said, lets get the action started: Start a new Docker container: sudo docker run -d codingtony/mule Find the id of the newly launched Docker container: sudo docker ps Examine low-level information about the newly launched Docker container: sudo docker inspect [container id or name here] Output similar to this will be printed to the console (portions removed to conserve space): [{ "AppArmorProfile": "", "Args": [], "Config": { ... }, "Created": "2015-01-12T07:58:47.913905369Z", "Driver": "aufs", "ExecDriver": "native-0.2", "HostConfig": { ... }, "HostnamePath": "/var/lib/docker/containers/68b40def7ad6a7f819bd654d5627ad1c3a0f40c84e0fb0f875760f1bd6790eef/hostname", "HostsPath": "/var/lib/docker/containers/68b40def7ad6a7f819bd654d5627ad1c3a0f40c84e0fb0f875760f1bd6790eef/hosts", "Id": "68b40def7ad6a7f819bd654d5627ad1c3a0f40c84e0fb0f875760f1bd6790eef", "Image": "bcd0f37d48d4501ad64bae941d95446b157a6f15e31251e26918dbac542d731f", "MountLabel": "", "Name": "/thirsty_darwin", "NetworkSettings": { ... }, "Path": "/opt/mule/bin/mule", "ProcessLabel": "", "ResolvConfPath": "/var/lib/docker/containers/68b40def7ad6a7f819bd654d5627ad1c3a0f40c84e0fb0f875760f1bd6790eef/resolv.conf", "State": { ... }, "Volumes": {}, "VolumesRW": {} }] Locate the “Driver” node (highlighted in the above output) and ensure that its value is “aufs”. If it is not, you may need to modify the directory paths below replacing “aufs” with the value of this node. Personally I have only seen the “aufs” value at this node so anything else is uncharted territory to me. Copy the long hexadecimal value that can be found at the “Id” node (also highlighted in the above output). This is the long id of the Docker container. In a terminal window, issue the following command, inserting the long id of your container where noted: sudo ls -al /var/lib/docker/aufs/mnt/[long container id here] You are now looking at the root of the volume used by the Docker container you just launched. In the same terminal window, issue the following command: sudo ls -al /var/lib/docker/aufs/mnt/[long container id here]/opt The output from this command should look like this: total 12 drwxr-xr-x 4 root root 4096 jan 12 15:58 . drwxr-xr-x 75 root root 4096 jan 12 15:58 .. lrwxrwxrwx 1 root root 26 aug 10 04:19 mule -> /opt/mule-standalone-3.5.0 drwxr-xr-x 17 409 409 4096 jan 12 15:58 mule-standalone-3.5.0 Examine this line in the Dockerfile:RUN ln -s /opt/mule-standalone-3.5.0 /opt/muleWe see that a symbolic link is created and that the directory name and the name of the symbolic link matches the output we saw earlier. This matches the directory output in the previous step. To examine the Mule log file that we looked at when binding volumes earlier, use the following command: sudo cat /var/lib/docker/aufs/mnt/[long container id here]/opt/mule-standalone-3.5.0/logs/mule.log Next we create a new file in the Docker container using vi: sudo vi /var/lib/docker/aufs/mnt/[long container id here]/opt/mule-standalone-3.5.0/test.txt Enter some text into the new file by first pressing i and the type the text. When you are finished entering the text, press the Escape key and write the file to disk by typing the characters “:wq” without quotes. This writes the new contents of the file to disk and quits the editor. Leave the Docker container running after you are finished. In the next section, we are going to look at the file we just created from inside the Docker container. We have seen that we can examine the file system of a Docker container without binding volumes. It is also possible to copy or move files from the host file-system to the container’s file system using the regular commands. Root privileges are required both when examining and writing to the Docker container’s file system. Entering a Docker Container In order to verify that the file we just created in the host was indeed written to the Docker container, we are going to start a bash shell in the running Docker container and examine the location where the new file is expected to be located and the contents of the file. In the process we will see how we can execute commands in a Docker container from the host. Issue the command below in a terminal window. The exec Docker command is used to run a command, bash in this case, in a running Docker container. The -i flags tell Docker to keep the input stream open while the command is being executed. In this example, it allows us to enter commands into the bash shell running inside the Docker container. The -t flag cause Docker to allocate a text terminal to which the output from the command execution is printed. sudo docker exec -i -t [container id or name here] bash Note the prompt, which should change to [user]@[Docker container id]. In my case it looks like this: root@3ea374a280da:/# Go to the Mule installation directory using this command: cd /opt/mule-standalone-3.5.0/ Examine the contents of the directory: ls -al Among the other files, you should see the “test.txt” file: -rw-r--r-- 1 root root 53 Jan 14 03:19 test.txt Examine the contents of the “text.txt” file. The contents of the file should match what you entered earlier. cat text.txt Exit to the host OS: exit Stop and remove the container: sudo docker stop [container id or name here] sudo docker rm [container id or name here] We have seen that we can execute commands in a running Docker container. In this particular example, we used it to execute the bash shell and examine a file. I draw the conclusion that I should be able to set up a Docker image that contains a very controlled environment for some type of test and then create a container from that image and start the test from the host. Deploying a Mule Application In this section we will look at deploying a Mule application to an instance of the Mule ESB running in a Docker container. We will use volume binding, that we looked at in the section on files and Docker containers, to share directories in the host with the Docker container in order to make it easy to deploy applications, modify running applications, examine logs etc. Preparations Before deploying the application, we need to make some preparations: First of all, we restore the original log-level that we changed earlier. In this example, there will be log output when the applications we will deploy is run and we can limit the log generated by Mule. Edit the log4j.properties file in the “mule-root/conf” directory in the host and set the log-level on the last line in the file back to “INFO” and add one line, as in the listing below. The last three lines should now look like this: # Mule classes log4j.logger.org.mule=INFO log4j.logger.org.mule.tck.functional=DEBUG Next, we create the Mule application which we will deploy to the Mule ESB running in Docker: In some directory, create a file named “mule-deploy.properties” with the following contents: redeployment.enabled=true encoding=UTF-8 domain=default config.resources=HelloWorld.xml In the same directory create a file named “HelloWorld.xml”. This file contains the Mule configuration for our example application: Create a zip-archive named “mule-hello.zip” containing the two files created above: zip mule-hello.zip mule-deploy.properties HelloWorld.xml Deploy the Mule Application Before you start the Docker container in which the Mule EBS will run, make sure that you have created and prepared the directories in the host as described in the section Files and Docker Containers above. Start a new Mule Docker container using the command that we used when binding volumes: sudo docker run -d -v ~/mule-root/apps:/opt/mule/apps -v ~/mule-root/conf:/opt/mule/conf -v ~/mule-root/logs:/opt/mule/logs codingtony/mule As before, the -v option tells Docker to bind three directories in the host to three locations in the Docker container’s file system. Find the IP-address of the Docker container: sudo docker inspect [container id or name here] | grep IPAddress In my case, I see the following line which reveals the IP-address of the Docker container: “IPAddress”: “172.0.17.2”, Open a terminal window or tab and examine the Mule log. Leave this window or tab open during the exercise, in order to be able to verify the output from Mule. tail -f ~/mule-root/logs/mule.log Copy the zip-archive “mule-hello.zip” created earlier to the host directory ~/mule-root/apps/. Verify that the application has been deployed without errors in the Mule log: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Started app 'mule-hello' + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Leave the Docker container running after you are finished. In the next section we will look at how to access endpoints exposed by applications running in Docker containers. By binding directories in the host thus making them available in the Docker container, it becomes very simple to deploy Mule applications to an instance of Mule ESB running in a Docker container. I am considering this setup for a production environment as well, since it will enable me to perform backups of the directories containing Mule applications and configuration without having to access the Docker container’s file system. It is also in accord with the idea that a Docker container should be able to be quickly and easily restarted, which I feel it would not be if I had to deploy a number of Mule applications to it in order to recreate its previous state. Accessing Endpoints We now know that we can run the Mule ESB in a Docker container, we can deploy applications and examine the logs quite easily but one final, very important question remains to be answered; how to access endpoints exposed by applications running in a Docker container. This section assumes that the Mule application we deployed to Mule in the previous section is still running. In the host, open a web-browser and issue a request to the Docker container’s IP-address at port 8181. In my case, the URL is http://172.17.0.2:8181 Alternatively use the curl command in a terminal window. In my case I would write: curl 172.17.0.2:8181 The result should be a greeting in the following format: Hello World! It is now: 2015-01-14T07:39:03.942Z In addition, you should be able to see that a message was received in the Mule log. Now try the URL http://localhost:8181 You will get a message saying that the connection was refused, provided that you do not already have a service listening at that port. If you have another computer available that is connected to the same network as the host computer running Ubuntu, do the following: – Find the IP-address of the Ubuntu host computer using the ifconfigcommand. – In a web-browser on the other computer, try accessing port 8181 at the IP-address of the Ubuntu host computer. Again you will get a message saying that the connection was refused. Stop and remove the container: sudo docker stop [container id or name here] sudo docker rm [container id or name here] Without any particular measures taken, we see that we can access a service exposed in a Docker container from the Docker host but we did not succeed in accessing the service from another computer. To make a service exposed in a Docker container reachable from outside of the host, we need to tell Docker to publish a port from the Docker container to a port in the host using the -p flag: Launch a new Docker container using the following command: sudo docker run -d -p 8181:8181 -v ~/mule-root/apps:/opt/mule/apps -v ~/mule-root/conf:/opt/mule/conf -v ~/mule-root/logs:/opt/mule/logs codingtony/mule The added flag -p 8181:8181 makes the service exposed at port 8181 in the Docker container available at port 8181 in the host. Try accessing the URL http://localhost:8181 from a web-browser on the host computer.The result should be a greeting of the form we have seen earlier. Try accessing port 8181 at the IP-address of the Ubuntu host computer from another computer.This should also result in a greeting message. Stop and remove the container: sudo docker stop [container id or name here] sudo docker rm [container id or name here] Using the -p flag, we have seen that we can expose a service in a Docker container so that it becomes accessible from outside of the host computer. However, we also see that this information need to be supplied at the time of launching the Docker container. The conclusions that I draw from this is that: I can test and develop against a Mule ESB instance running in a Docker container without having to publish any ports, provided that my development computer is the Docker host computer. In a production environment or any other environment that need to expose services running in a Docker container to “the outside world” and where services will be added over time, I would consider deploying an Apache HTTP Server or NGINX on the Docker host computer and use it to proxy the services that are to be exposed. This way I can avoid re-launching the Docker container each time a new service is added and I can even (temporarily) redirect the proxy to some other computer if I need to perform some maintenance. Is There More? Of course! This article should only be considered an introduction and I am just a beginner with Docker. I hope I will have the time and inspiration to write more about Docker as I learn more.
January 20, 2015
by Ivan K
· 27,757 Views · 4 Likes
article thumbnail
Using Netflix Hystrix Annotations with Spring
My objective here is to recreate a similar set-up in a smaller unit test mode.
January 12, 2015
by Biju Kunjummen
· 36,962 Views · 1 Like
article thumbnail
Java EE Interceptors
History I think it’s important to take a look at the evolution of Interceptors in Java EE because of the simple fact that it started as an EJB-specific item and later evolved into a separate spec which is now open for extension by other Java EE specifications. Version 1.0 Interceptors were first introduced in EJB 3.0 (part of Java EE 5). Interceptors did not have a dedicated spec but they were versioned 1.0 and bought basic AOP related features to managed beans (POJOs) via simple annotations @AroundInvoke – to annotate methods containing the interception logic for target class methods @Intercerptors – to bind the the interceptor classes with their target classes/methods Capability to configure interceptors for an entire module (EJB JAR) via the deployment descriptor @ExcludeDefaultInterceptors – to mute default interceptors defined in the deployment descriptor @ExcludeClassInterceptors – to mute a globally defined (class level) interceptor for a particular method/constructor of the class Interceptors 1.1 Along came Java EE 6 with EJB 3.1 – Interceptors 1.1 was still included in the EJB spec document @InterceptorBinding – a type safe way of specifying interceptors of a class or a method. Please note that this annotation was leveraged by CDI 1.0 (another specification introduced in Java EE 6) and its details are present in the CDI 1.0 spec doc rather than EJB 3.1 (light bulb moment … at least for me) @Interceptor – Used to explicitly declare a class containing an interception logic in a specific method (annotated with @AroundInvoke etc) as an interceptor along with an appropriate Interceptor Binding. This too was mentioned in the CDI 1.0 documentation only. @AroundTimeout – used to intercept time outs of EJB timers along with a way to obtain an instance of the Timer being intercepted (viajavax.interceptor.InvocationContext.getTimer()) Interceptors 1.2 Interceptors were split off into an individual spec in Java EE 7 and thus Interceptors 1.2came into being Interceptors 1.2 was a maintenance release on top of 1.1 and hence the JSR number still remained the same as EJB 3.1 (JSR 318) Interceptor.Priority (static class) – to provide capability to define the order (priority) in which the interceptors need to invoked. @AroundConstruct – used to intercept the construction of the target class i.e. invoke logic prior to the constructor of the target class is invoked It’s important to bear in mind that Interceptors are applicable to managed beans in general. Managed Beans themselves are simple POJOs which are privileged to basic services by the container – Interceptors are one of them along with life cycle callbacks, resource injection. Memory Aid It’s helpful to think of Interceptors as components which can interpose on beans throughout their life cycle before they are even constructed – @AroundConstruct after they are constructed – @PostConstruct during their life time (method invocation) – @AroundInvoke prior to destruction – @PreDestroy time outs of EJBs – @AroundTimeout Let’s look at some of the traits of Interceptors in more detail and try to answer questions like where are they applied and what do they intercept ? how to bind interceptors to the target (class) they are supposed to intercept ? Interceptors Types (based on the intercepted component) Method Interceptors Achieved by @AroundInvoke public class MethodInterceptor{ @AroundInvoke public Object interceptorMethod(InvocationContext ictx) throws Exception{ //logic goes here } } @Stateless public class AnEJB{ @Interceptors(MethodInterceptor.class) public void bizMethod(){ //any calls to this method will be intercepted by MethodInterceptor.interceptorMethod() } } The method containing the logic can be part of separate class as well as the target class (class to be intercepted) itself. Lifecycle Callback interceptors Decorate the method with @AroundConstruct in order to intercept the constructor invocation for a class public class ConstructorInterceptor{ @AroundConstruct public Object interceptorMethod(InvocationContext ictx) throws Exception{ //logic goes here } } public class APOJO{ @Interceptors(ConstructorInterceptor.class) public APOJO(){ //any calls to this constructor will be intercepted by ConstructorInterceptor.interceptorMethod() } } The method annotated with @AroundConstruct cannot be a part of the intercepted class. It has to be defined using a separate Interceptor class Use the @PostConstruct annotation on a method in order to intercept a call back method on a managed bean. Just to clarify again – the Interceptor spec does not define a new annotation as such. One needs to reuse the @PostConstruct (part of theCommon Annotations spec) on the interceptor method. public class PostConstructInterceptor{ @PostConstruct public void interceptorMethod(InvocationContext ictx) throws Exception{ //logic goes here } } @Interceptors(PostConstructInterceptor.class) public class APOJO{ @PostConstruct public void bizMethod(){ //any calls to this method will be intercepted by PostConstructInterceptor.interceptorMethod() } } The @PreDestroy (another call back annotation defined in Common Annotations spec) annotation is used in a similar fashion Time-out Interceptors As mentioned above – @AroundTimeout used to intercept time outs of EJB timers along with a way to obtain an instance of the Timer being intercepted (viajavax.interceptor.InvocationContext.getTimer()) Applying/Binding Interceptors Using @Interceptors As shown in above examples – just use the @Interceptors annotation to specify the interceptor classes @Interceptors can be applied on a class level (automatically applicable to all the methods of a class), to a particular method or multiple methods and constructor in case of a constructor specific interceptor using @AroundConstruct Using @IntercerptorBinding Interceptor Bindings (explained above) – Use @IntercerptorBinding annotation to define a binding annotation which is further used on the interceptor class as well as the target class (whose method, constructor etc needs to be intercepted) @InterceptorBinding @Target({TYPE, METHOD, CONSTRUCTOR}) @Retention(RUNTIME) public @interface @Auditable { } @Auditable @Interceptor public class AuditInterceptor { @AroundInvoke public Object audit(InvocationContext ictx) throws Exception{ //logic goes here } } @Stateless @Auditable public class AnEJB{ public void bizMethod(){ //any calls to this method will be intercepted by AuditInterceptor.audit() } } Deployment Descriptor One can also use deployment descriptors to bind interceptors and target classes either in an explicit fashion as well as in override mode to annotations. This was a rather quick overview of Java EE interceptors. Hopefully the right trigger for you to dig deeper :-) Cheers !
January 9, 2015
by Abhishek Gupta DZone Core CORE
· 31,171 Views · 8 Likes
article thumbnail
How to Integrate Jersey in a Spring MVC Application
I have recently started to build a public REST API with Java for Podcastpedia.org and for the JAX-RS implementation I have chosen Jersey, as I find it “natural” and powerful – you can find out more about it by following the Tutorial – REST API design and implementation in Java with Jersey and Spring. Because Podcastpedia.org is a web application powered by Spring MVC, I wanted to integrate both frameworks in podcastpedia-web, to take advantage of the backend service functionality already present in the project. Anyway this short post will present the steps I had to take to make the integration between the two frameworks work. Framework versions Current versions used: 4.1.0.RELEASE 2.14 Project dependencies The Jersey Spring extension must be present in your project’s classpath. If you are using Maven add it to the pom.xml file of your project: org.glassfish.jersey.ext jersey-spring3 ${jersey.version} org.springframework spring-core org.springframework spring-web org.springframework spring-beans org.glassfish.jersey.media jersey-media-json-jackson ${jersey.version} com.fasterxml.jackson.jaxrs jackson-jaxrs-base com.fasterxml.jackson.core jackson-annotations com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider Note: I have explicitly excluded the Spring core and the Jackson implementation libraries as they have been already imported in the project with preferred versions. Web.xml configuration In the web.xml, in addition to the Spring MVC servlet configuration I added the jersey-servlet configuration, that will map all requests starting with/api/: Spring MVC Dispatcher Servlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:spring/application-context.xml 1 Spring MVC Dispatcher Servlet / jersey-serlvet org.glassfish.jersey.servlet.ServletContainer javax.ws.rs.Application org.podcastpedia.web.api.JaxRsApplication 2 jersey-serlvet /api/* Well, that’s pretty much it… If you have any questions drop me a line or comment in the discussion below. In the coming post I will present some of the results of this integration, by showing how to call one method of the REST public API with jQuery, to dynamically load recent episodes of a podcast, so stay tuned.
January 8, 2015
by Adrian Matei
· 20,091 Views
article thumbnail
How to Mock a Spring Bean Without Springockito
NEW EDIT: As of Spring Boot 1.4.0, faking of Spring Beans is supported natively via annotation @MockBean. Read Spring Boot docs for more info. OLD EDIT: Here is better example how to mock Spring bean. I've worked with Spring for several years. But I was always frustrated with how messy can XML configuration become. As various annotations and possibilities of Java configuration were popping up, I started to enjoy programming with Spring. That is why I strongly entourage using Java configuration. In my opinion, XML configuration is suitable only when you need to have visualized Spring Integration or Spring Batch flow. Hopefully Spring Tool Suite will be able to visualize Java configurations for these frameworks also. One of the nasty aspects of XML configuration is that it often leads to huge XML configuration files. Developers therefore often create test context configuration for integration testing. But what is the purpose of integration testing, when there isn’t production wiring tested? Such integration test has very little value. So I was always trying to design my production contexts in testable fashion. I except that when you are creating new project / module you would avoid XML configuration as much as possible. So with Java configuration you can create Spring configuration per module / package and scan them in main context (@Configuration is also candidate for component scanning). This way you can naturally create islands Spring beans. These islands can be easily tested in isolation. But I have to admit that it’s not always possible to test production Java configuration as is. Rarely you need to amend behavior or spy on certain beans. There is library for it called Springockito. To be honest I didn’t use it so far, because I always try to design Spring configuration to avoid need for mocking. Looking at Springockito pace of development and number of open issues, I would be little bit worried to introduce it into my test suite stack. Fact that last release was done before Spring 4 release brings up questions like “Is it possible to easily integrate it with Spring 4?”. I don’t know, because I didn’t try it. I prefer pure Spring approach if I need to mock Spring bean in integration test. Spring provides @Primary annotation for specifying which bean should be preferred in the case when two beans with same type are registered. This is handy because you can override production bean with fake bean in integration test. Let’s explore this approach and some pitfalls on examples. I chose this simplistic / dummy production code structure for demonstration: @Repository public class AddressDao { public String readAddress(String userName) { return "3 Dark Corner"; } } @Service public class AddressService { private AddressDao addressDao; @Autowired public AddressService(AddressDao addressDao) { this.addressDao = addressDao; } public String getAddressForUser(String userName){ return addressDao.readAddress(userName); } } @Service public class UserService { private AddressService addressService; @Autowired public UserService(AddressService addressService) { this.addressService = addressService; } public String getUserDetails(String userName){ String address = addressService.getAddressForUser(userName); return String.format("User %s, %s", userName, address); } } AddressDao singleton bean instance is injected into AddressService. AddressService is similarly used in UserService. I have to warn you at this stage. My approach is slightly invasive to production code. To be able to fake existing production beans, we have to register fake beans in integration test. But these fake beans are usually in the same package sub-tree as production beans (assuming you are using standard Maven files structure: “src/main/java” and “src/test/java”). So when they are in the same package sub-tree, they would be scanned during integration tests. But we don’t want to use all bean fakes in all integration tests. Fakes could break unrelated integration tests. So we need to have mechanism, how to tell the test to use only certain fake beans. This is done by excluding fake beans from component scanning completely. Integration test explicitly define which fake/s are being used (will show this later). Now let’s take a look at mechanism of excluding fake beans from component scanning. We define our own marker annotation: public @interface BeanMock { } And exclude @BeanMock annotation from component scanning in main Spring configuration. @Configuration @ComponentScan(excludeFilters = @Filter(BeanMock.class)) @EnableAutoConfiguration public class Application { } Root package of component scan is current package of Application class. So all above production beans needs to be in same package or sub-package. We are now need to create integration test forUserService. Let’s spy on address service bean. Of course such testing doesn’t make practical sense with this production code, but this is just example. So here is our spying bean: @Configuration @BeanMock public class AddressServiceSpy { @Bean @Primary public AddressService registerAddressServiceSpy(AddressService addressService) { return spy(addressService); } } Production AddressService bean is autowired from production context, wrapped into Mockito‘s spy and registered as primary bean for AddressService type. @Primary annotation makes sure that our fake bean will be used in integration test instead of production bean. @BeanMock annotation ensures that this bean can’t be scanned by Application component scanning. Let’s take a look at the integration test now: @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { Application.class, AddressServiceSpy.class }) public class UserServiceITest { @Autowired private UserService userService; @Autowired private AddressService addressService; @Test public void testGetUserDetails() { // GIVEN - spring context defined by Application class // WHEN String actualUserDetails = userService.getUserDetails("john"); // THEN Assert.assertEquals("User john, 3 Dark Corner", actualUserDetails); verify(addressService, times(1)).getAddressForUser("john"); } } @SpringApplicationConfigration annotation has two parameters. First (Application.class) declares Spring configuration under test. Second parameter (AddressServiceSpy.class) specifies fake bean that will be loaded for our testing into Spring IoC container. It’s obvious that we can use as many bean fakes as needed, but you don’t want to have many bean fakes. This approach should be used rarely and if you observe yourself using such mocking often, you are probably having serious problem with tight coupling in your application or within your development team in general. TDD methodology should help you target this problem. Bear in mind: “Less mocking is always better!”. So consider production design changes that allow for lower usage of mocks. This applies also for unit testing. Within integration test we can autowire this spy bean and use it for various verifications. In this case we verified if testing method userService.getUserDetails called methodaddressService.getAddressForUser with parameter “john”. I have one more example. In this case we wouldn’t spy on production bean. We will mock it: @Configuration @BeanMock public class AddressDaoMock { @Bean @Primary public AddressDao registerAddressDaoMock() { return mock(AddressDao.class); } } Again we override production bean, but this time we replace it with Mockito’s mock. We can than record behavior for mock in our integration test: @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { Application.class, AddressDaoMock.class }) public class AddressServiceITest { @Autowired private AddressService addressService; @Autowired private AddressDao addressDao; @Test public void testGetAddressForUser() { // GIVEN when(addressDao.readAddress("john")).thenReturn("5 Bright Corner"); // WHEN String actualAddress = addressService.getAddressForUser("john"); // THEN Assert.assertEquals("5 Bright Corner", actualAddress); } @After public void resetMock() { reset(addressDao); } } We load mocked bean via @SpringApplicationConfiguration‘s parameter. In test method, we stubaddressDao.readAddress method to return “5 Bright Corner” string when “john” is passed to it as parameter. But bear in mind that recorded behavior can be carried to different integration test via Spring context. We don’t want tests affecting each other. So you can avoid future problems in your test suite by reseting mocks after test. This is done in method resetMock. Source code is on Github.
January 4, 2015
by Lubos Krnac
· 21,359 Views
article thumbnail
Spring Boot: Creating Microservices on Java
Learn all about creating a microservices architecture on Java in this great tutorial.
December 29, 2014
by Alexandre Lourenco
· 220,849 Views · 28 Likes
article thumbnail
Test your C++ skills - find bugs in popular open-source projects
Authors of PVS-Studio static code analyzers offer programmers to test their sight and to try finding errors in C/C++ code fragments. Code analyzers work tirelessly and are able to find many bugs that can be difficult to notice. We chose some code fragments in which we had founded some errors using PVS-Studio. Quiz is not intended to check C++ language knowledge. There are many quality and interesting tests. For instance, we would recommend this C++ Quiz then. In our case, we made our test just for fun. We quite frequently hear an opinion that code analyzers are pointless tools. It is possible to find misplaced parenthesis or comma in five seconds. However, analyzer would not find difficult logical errors. Therefore, this tool could be useful only for students. We decided to troll these people. There is a time limit in tests. We ask them to find an error in five seconds. Well, OK, not in five seconds, but in a minute. Fifteen randomly selected problems would be shown. Every solved problem worth one point, but only if user provided the answer in one minute. We want to stress that we are not talking about syntax errors. We found all these code fragments in open-source projects that compiles flawlessly. Let us explain on a pair of examples how to point out the correct answer. First example. For instance, you got this code: The bug here is highlighted with red color. Of course, there would be no such emphasizing in a quiz problem. Programmer accidently made a misprint and wrote index 3 instead of index 2. Mouse cursor movement would highlight fragments of code, such as words and numbers. You should point the cursor into number 3 and press left mouse button. This would be the correct answer. Second example. It is not always possible to point out the error exactly. Buffer size should be compared with number 48. An excess sizeof() operator was put there by accident. In result, buffer size is compared with size of int type. At my opinion, an error there is in sizeof operator, and it is required to point it out to score a correct answer. However, without knowledge about the whole text, it is possible to think this way. Sizeof operator should have evaluated the size of some buffer, but accidently evaluates the value of the macro. The error is in “SSL3_MASTER_SECRET_LENGTH” usage. In this case, the answer will be scored no matter what you choose: “sizeof” or “SSL3_MASTER_SECRET_LENGTH”. Good luck! You can start a game. Footnote. Test does not support mobile devices. It is very easy to miss with finger. We are working on new version of tests with better mobile devices support, new problems to solve etc. However, it is not implemented yet. We offer you to subscribe on twitter to read about our new and interesting news and to read about new things in a C++ world.
December 26, 2014
by Andrey Karpov
· 12,531 Views
article thumbnail
RabbitMQ - Processing Messages Serially Using Spring Integration Java DSL
If you ever have a need to process messages serially with RabbitMQ with a cluster of listeners processing the messages, the best way that I have seen is to use a "exclusive consumer" flag on a listener with 1 thread on each listener processing the messages. Exclusive consumer flag ensures that only 1 consumer can read messages from the specific queue, and 1 thread on that consumer ensures that the messages are processed serially. There is a catch however, I will go over it later. Let me demonstrate this behavior with a Spring Boot and Spring Integration based RabbitMQ message consumer. First, this is the configuration for setting up a queue using Spring java configuration, note that since this is a Spring Boot application, it automatically creates a RabbitMQ connection factory when the Spring-amqp library is added to the list of dependencies: @Configuration @Configuration public class RabbitConfig { @Autowired private ConnectionFactory rabbitConnectionFactory; @Bean public Queue sampleQueue() { return new Queue("sample.queue", true, false, false); } } Given this sample queue, a listener which gets the messages from this queue and processes them looks like this, the flow is written using the excellent Spring integration Java DSL library: @Configuration public class RabbitInboundFlow { private static final Logger logger = LoggerFactory.getLogger(RabbitInboundFlow.class); @Autowired private RabbitConfig rabbitConfig; @Autowired private ConnectionFactory connectionFactory; @Bean public SimpleMessageListenerContainer simpleMessageListenerContainer() { SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer(); listenerContainer.setConnectionFactory(this.connectionFactory); listenerContainer.setQueues(this.rabbitConfig.sampleQueue()); listenerContainer.setConcurrentConsumers(1); listenerContainer.setExclusive(true); return listenerContainer; } @Bean public IntegrationFlow inboundFlow() { return IntegrationFlows.from(Amqp.inboundAdapter(simpleMessageListenerContainer())) .transform(Transformers.objectToString()) .handle((m) -> { logger.info("Processed {}", m.getPayload()); }) .get(); } } The flow is very concisely expressed in the inboundFlow method, a message payload from RabbitMQ is transformed from byte array to String and finally processed by simply logging the message to the logs The important part of the flow is the listener configuration, note the flag which sets the consumer to be an exclusive consumer and within this consumer the number of threads processing is set to 1. Given this even if multiple instances of the application is started up only 1 of the listeners will be able to connect and process messages. Now for the catch, consider a case where the processing of messages takes a while to complete and rolls back during processing of the message. If the instance of the application handling the message were to be stopped in the middle of processing such a message, then the behavior is a different instance will start handling the messages in the queue, when the stopped instance rolls back the message, the rolled back message is then delivered to the new exclusive consumer, thus getting a message out of order. If you are interested in exploring this further, here is a github project to play with this feature: https://github.com/bijukunjummen/test-rabbit-exclusive
December 26, 2014
by Biju Kunjummen
· 21,816 Views
article thumbnail
ORM Is an Offensive Anti-Pattern
{editor's note: thanks to yegor bugayenko, a new mvb at dzone. among other things, yegor blogs about java and devops. we're pleased to have him on board as a most valuable blogger. check out his blog, yegor256.com .} tl;dr orm is a terrible anti-pattern that violates all principles of object-oriented programming, tearing objects apart and turning them into dumb and passive data bags. there is no excuse for orm existence in any application, be it a small web app or an enterprise-size system with thousands of tables and crud manipulations on them. what is the alternative? sql-speaking objects . vinni-pukh (1969) by fyodor khitruk how orm works object-relational mapping (orm) is a technique (a.k.a. design pattern) of accessing a relational database from an object-oriented language (java, for example). there are multiple implementations of orm in almost every language; for example: hibernate for java, activerecord for ruby on rails, doctrine for php, and sqlalchemy for python. in java, the orm design is even standardized as jpa . first, let's see how orm works, by example. let's use java, postgresql, and hibernate. let's say we have a single table in the database, called post : +-----+------------+--------------------------+ | id | date | title | +-----+------------+--------------------------+ | 9 | 10/24/2014 | how to cook a sandwich | | 13 | 11/03/2014 | my favorite movies | | 27 | 11/17/2014 | how much i love my job | +-----+------------+--------------------------+ now we want to crud-manipulate this table from our java app (crud stands for create, read, update, and delete). first, we should create a post class (i'm sorry it's so long, but that's the best i can do): @entity @table(name = "post") public class post { private int id; private date date; private string title; @id @generatedvalue public int getid() { return this.id; } @temporal(temporaltype.timestamp) public date getdate() { return this.date; } public title gettitle() { return this.title; } public void setdate(date when) { this.date = when; } public void settitle(string txt) { this.title = txt; } } before any operation with hibernate, we have to create a session factory: sessionfactory factory = new annotationconfiguration() .configure() .addannotatedclass(post.class) .buildsessionfactory(); this factory will give us "sessions" every time we want to manipulate with post objects. every manipulation with the session should be wrapped in this code block: session session = factory.opensession(); try { transaction txn = session.begintransaction(); // your manipulations with the orm, see below txn.commit(); } catch (hibernateexception ex) { txn.rollback(); } finally { session.close(); } when the session is ready, here is how we get a list of all posts from that database table: list posts = session.createquery("from post").list(); for (post post : (list) posts){ system.out.println("title: " + post.gettitle()); } i think it's clear what's going on here. hibernate is a big, powerful engine that makes a connection to the database, executes necessary sql select requests, and retrieves the data. then it makes instances of class post and stuffs them with the data. when the object comes to us, it is filled with data, and we should use getters to take them out, like we're using gettitle() above. when we want to do a reverse operation and send an object to the database, we do all of the same but in reverse order. we make an instance of class post , stuff it with the data, and ask hibernate to save it: post post = new post(); post.setdate(new date()); post.settitle("how to cook an omelette"); session.save(post); this is how almost every orm works. the basic principle is always the same — orm objects are anemic envelopes with data. we are talking with the orm framework, and the framework is talking to the database. objects only help us send our requests to the orm framework and understand its response. besides getters and setters, objects have no other methods. they don't even know which database they came from. this is how object-relational mapping works. what's wrong with it, you may ask? everything! what's wrong with orm? seriously, what is wrong? hibernate has been one of the most popular java libraries for more than 10 years already. almost every sql-intensive application in the world is using it. each java tutorial would mention hibernate (or maybe some other orm like toplink or openjpa) for a database-connected application. it's a standard de-facto and still i'm saying that it's wrong? yes. i'm claiming that the entire idea behind orm is wrong. its invention was maybe the second big mistake in oop after null reference . actually, i'm not the only one saying something like this, and definitely not the first. a lot about this subject has already been published by very respected authors, including ormhate by martin fowler, object-relational mapping is the vietnam of computer science by jeff atwood, the vietnam of computer science by ted neward, orm is an anti-pattern by laurie voss, and many others. however, my argument is different than what they're saying. even though their reasons are practical and valid, like "orm is slow" or "database upgrades are hard", they miss the main point. you can see a very good, practical answer to these practical arguments given by bozhidar bozhanov in his orm haters don’t get it blog post. the main point is that orm, instead of encapsulating database interaction inside an object, extracts it away, literally tearing a solid and cohesive living organism apart. one part of the object keeps the data while another one, implemented inside the orm engine (session factory), knows how to deal with this data and transfers it to the relational database. look at this picture; it illustrates what orm is doing. i, being a reader of posts, have to deal with two components: 1) the orm and 2) the "obtruncated" object returned to me. the behavior i'm interacting with is supposed to be provided through a single entry point, which is an object in oop. in the case of orm, i'm getting this behavior via two entry points — the orm and the "thing", which we can't even call an object. because of this terrible and offensive violation of the object-oriented paradigm, we have a lot of practical issues already mentioned in respected publications. i can only add a few more. sql is not hidden . users of orm should speak sql (or its dialect, like hql ). see the example above; we're calling session.createquery("from post") in order to get all posts. even though it's not sql, it is very similar to it. thus, the relational model is not encapsulated inside objects. instead, it is exposed to the entire application. everybody, with each object, inevitably has to deal with a relational model in order to get or save something. thus, orm doesn't hide and wrap the sql but pollutes the entire application with it. difficult to test . when some object is working a list of posts, it needs to deal with an instance of sessionfactory . how can we mock this dependency? we have to create a mock of it? how complex is this task? look at the code above, and you will realize how verbose and cumbersome that unit test will be. instead, we can write integration tests and connect the entire application to a test version of postgresql. in that case, there is no need to mock sessionfactory , but such tests will be rather slow, and even more important, our having-nothing-to-do-with-the-database objects will be tested against the database instance. a terrible design. again, let me reiterate. practical problems of orm are just consequences. the fundamental drawback is that orm tears objects apart, terribly and offensively violating the very idea of what an object is . sql-speaking objects what is the alternative? let me show it to you by example. let's try to design that class, post , my way. we'll have to break it down into two classes: post and posts , singular and plural. i already mentioned in one of my previous articles that a good object is always an abstraction of a real-life entity. here is how this principle works in practice. we have two entities: database table and table row. that's why we'll make two classes; posts will represent the table, and post will represent the row. as i also mentioned in that article , every object should work by contract and implement an interface. let's start our design with two interfaces. of course, our objects will be immutable. here is how posts would look: @immutable interface posts { iterable iterate(); post add(date date, string title); } this is how a single post would look: @immutable interface post { int id(); date date(); string title(); } here is how we will list all posts in the database table: posts posts = // we'll discuss this right now for (post post : posts.iterate()){ system.out.println("title: " + post.title()); } here is how we will create a new post: posts posts = // we'll discuss this right now posts.add(new date(), "how to cook an omelette"); as you see, we have true objects now. they are in charge of all operations, and they perfectly hide their implementation details. there are no transactions, sessions, or factories. we don't even know whether these objects are actually talking to the postgresql or if they keep all the data in text files. all we need from posts is an ability to list all posts for us and to create a new one. implementation details are perfectly hidden inside. now let's see how we can implement these two classes. i'm going to use jcabi-jdbc as a jdbc wrapper, but you can use something else or just plain jdbc if you like. it doesn't really matter. what matters is that your database interactions are hidden inside objects. let's start with posts and implement it in class pgposts ("pg" stands for postgresql): @immutable final class pgposts implements posts { private final source dbase; public pgposts(datasource data) { this.dbase = data; } public iterable iterate() { return new jdbcsession(this.dbase) .sql("select id from post") .select( new listoutcome( new listoutcome.mapping() { @override public post map(final resultset rset) { return new pgpost(rset.getinteger(1)); } } ) ); } public post add(date date, string title) { return new pgpost( this.dbase, new jdbcsession(this.dbase) .sql("insert into post (date, title) values (?, ?)") .set(new utc(date)) .set(title) .insert(new singleoutcome(integer.class)) ); } } next, let's implement the post interface in class pgpost : @immutable final class pgpost implements post { private final source dbase; private final int number; public pgpost(datasource data, int id) { this.dbase = data; this.number = id; } public int id() { return this.number; } public date date() { return new jdbcsession(this.dbase) .sql("select date from post where id = ?") .set(this.number) .select(new singleoutcome(utc.class)); } public string title() { return new jdbcsession(this.dbase) .sql("select title from post where id = ?") .set(this.number) .select(new singleoutcome(string.class)); } } this is how a full database interaction scenario would look like using the classes we just created: posts posts = new pgposts(dbase); for (post post : posts.iterate()){ system.out.println("title: " + post.title()); } post post = posts.add(new date(), "how to cook an omelette"); system.out.println("just added post #" + post.id()); you can see a full practical example here . it's an open source web app that works with postgresql using the exact approach explained above — sql-speaking objects. what about performance? i can hear you screaming, "what about performance?" in that script a few lines above, we're making many redundant round trips to the database. first, we retrieve post ids with select id and then, in order to get their titles, we make an extra select title call for each post. this is inefficient, or simply put, too slow. no worries; this is object-oriented programming, which means it is flexible! let's create a decorator of pgpost that will accept all data in its constructor and cache it internally, forever: @immutable final class constpost implements post { private final post origin; private final date dte; private final string ttl; public constpost(post post, date date, string title) { this.origin = post; this.dte = date; this.ttl = title; } public int id() { return this.origin.id(); } public date date() { return this.dte; } public string title() { return this.ttl; } } pay attention: this decorator doesn't know anything about postgresql or jdbc. it just decorates an object of type post and pre-caches the date and title. as usual, this decorator is also immutable. now let's create another implementation of posts that will return the "constant" objects: @immutable final class constpgposts implements posts { // ... public iterable iterate() { return new jdbcsession(this.dbase) .sql("select * from post") .select( new listoutcome( new listoutcome.mapping() { @override public post map(final resultset rset) { return new constpost( new pgpost(rset.getinteger(1)), utc.gettimestamp(rset, 2), rset.getstring(3) ); } } ) ); } } now all posts returned by iterate() of this new class are pre-equipped with dates and titles fetched in one round trip to the database. using decorators and multiple implementations of the same interface, you can compose any functionality you wish. what is the most important is that while functionality is being extended, the complexity of the design is not escalating, because classes don't grow in size. instead, we're introducing new classes that stay cohesive and solid, because they are small. what about transactions? every object should deal with its own transactions and encapsulate them the same way as select or insert queries. this will lead to nested transactions, which is perfectly fine provided the database server supports them. if there is no such support, create a session-wide transaction object that will accept a "callable" class. for example: final class txn { private final datasource dbase; public t call(callable callable) { jdbcsession session = new jdbcsession(this.dbase); try { session.sql("start transaction").exec(); t result = callable.call(); session.sql("commit").exec(); return result; } catch (exception ex) { session.sql("rollback").exec(); throw ex; } } } then, when you want to wrap a few object manipulations in one transaction, do it like this: new txn(dbase).call( new callable() { @override public integer call() { posts posts = new pgposts(dbase); post post = posts.add(new date(), "how to cook an omelette"); posts.comments().post("this is my first comment!"); return post.id(); } } ); this code will create a new post and post a comment to it. if one of the calls fail, the entire transaction will be rolled back. this approach looks object-oriented to me. i'm calling it "sql-speaking objects", because they know how to speak sql with the database server. it's their skill, perfectly encapsulated inside their borders. related posts you may also find these posts interesting: how much your objects encapsulate? how an immutable object can have state and behavior? seven virtues of a good object how immutability helps paired brackets
December 22, 2014
by Yegor Bugayenko
· 57,821 Views · 5 Likes
article thumbnail
Message Processing With Spring Integration
Spring Integration provides an extension of the Spring framework to support the well-known Enterprise Integration Patterns. It enables lightweight messaging within Spring-based applications and supports integration with external systems. One of the most important goals of Spring Integration is to provide a simple model for building maintainable and testable enterprise integration solutions. Main Components : Message : It is a generic wrapper for any Java object combined with metadata used by the framework while handling that object. It consists of a payload and header(s). Message payload can be any Java Object and Message header is a String/Object Map covering header name and value. MessageBuilder is used to create messages covering payload and headers as follows : import org.springframework.messaging.Message; import org.springframework.messaging.support.MessageBuilder; Message message = MessageBuilder.withPayload("Message Payload") .setHeader("Message_Header1", "Message_Header1_Value") .setHeader("Message_Header2", "Message_Header2_Value") .build(); Message Channel : A message channel is the component through which messages are moved so it can be thought as a pipe between message producer and consumer. A Producer sends the message to a channel, and a consumer receives the message from the channel. A Message Channel may follow either Point-to-Point or Publish/Subscribe semantics. With a Point-to-Point channel, at most one consumer can receive each message sent to the channel. With Publish/Subscribe channels, multiple subscribers can receive each Message sent to the channel. Spring Integration supports both of these. In this sample project, Direct channel and null-channel are used. Direct channel is the default channel type within Spring Integration and simplest point-to-point channel option. Null Channel is a dummy message channel to be used mainly for testing and debugging. It does not send the message from sender to receiver but its send method always returns true and receive method returns null value. In addition to DirectChannel and NullChannel, Spring Integration provides different Message Channel Implementations such as PublishSubscribeChannel, QueueChannel, PriorityChannel, RendezvousChannel, ExecutorChannel and ScopedChannel. Message Endpoint : A message endpoint isolates application code from the infrastructure. In other words, it is an abstraction layer between the application code and the messaging framework. Main Message Endpoints : Transformer : A Message Transformer is responsible for converting a Message’s content or structure and returning the modified Message. For example : it may be used to transform message payload from one format to another or to modify message header values. Filter : A Message Filter determines whether the message should be passed to the message channel. Router : A Message Router decides what channel(s) should receive the Message next if it is available. Splitter : A Splitter breaks an incoming message into multiple messages and send them to the appropriate channel. Aggregator : An Aggregator combines multiple messages into a single message. Service Activator : A Service Activator is a generic endpoint for connecting a service instance to the messaging system. Channel Adapter : A Channel Adapter is an endpoint that connects a Message Channel to external system. Channel Adapters may be either inbound or outbound. An inbound Channel Adapter endpoint connects a external system to a MessageChannel. An outbound Channel Adapter endpoint connects a MessageChannel to a external system. Messaging Gateway : A gateway is an entry point for the messaging system and hides the messaging API from external system. It is bidirectional by covering request and reply channels. Also Spring Integration provides various Channel Adapters and Messaging Gateways (for AMQP, File, Redis, Gemfire, Http, Jdbc, JPA, JMS, RMI, Stream etc..) to support Message-based communication with external systems. Please visit Spring Integration Reference documentation for the detailed information. The following sample Cargo messaging implementation shows basic message endpoints’ behaviours for understanding easily. Cargo messaging system listens cargo messages from external system by using a CargoGateway Interface. Received cargo messages are processed by using CargoSplitter, CargoFilter, CargoRouter, CargoTransformer MessageEndpoints. After then, processed successful domestic and international cargo messages are sent to CargoServiceActivator. Cargo Messaging System’ s Spring Integration Flow is as follows : Let us take a look sample cargo messaging implementation. Used Technologies : JDK 1.8.0_25 Spring 4.1.2 Spring Integration 4.1.0 Maven 3.2.2 Ubuntu 14.04 Project Hierarchy is as follows : STEP 1 : Dependencies Dependencies are added to Maven pom.xml. 4.1.2.RELEASE 4.1.0.RELEASE org.springframework spring-context ${spring.version} org.springframework.integration spring-integration-core ${spring.integration.version} STEP 2 : Cargo Builder CargoBuilder is created to build Cargo requests. public class Cargo { public enum ShippingType { DOMESTIC, INTERNATIONAL } private final long trackingId; private final String receiverName; private final String deliveryAddress; private final double weight; private final String description; private final ShippingType shippingType; private final int deliveryDayCommitment; private final int region; private Cargo(CargoBuilder cargoBuilder) { this.trackingId = cargoBuilder.trackingId; this.receiverName = cargoBuilder.receiverName; this.deliveryAddress = cargoBuilder.deliveryAddress; this.weight = cargoBuilder.weight; this.description = cargoBuilder.description; this.shippingType = cargoBuilder.shippingType; this.deliveryDayCommitment = cargoBuilder.deliveryDayCommitment; this.region = cargoBuilder.region; } // Getter methods... @Override public String toString() { return "Cargo [trackingId=" + trackingId + ", receiverName=" + receiverName + ", deliveryAddress=" + deliveryAddress + ", weight=" + weight + ", description=" + description + ", shippingType=" + shippingType + ", deliveryDayCommitment=" + deliveryDayCommitment + ", region=" + region + "]"; } public static class CargoBuilder { private final long trackingId; private final String receiverName; private final String deliveryAddress; private final double weight; private final ShippingType shippingType; private int deliveryDayCommitment; private int region; private String description; public CargoBuilder(long trackingId, String receiverName, String deliveryAddress, double weight, ShippingType shippingType) { this.trackingId = trackingId; this.receiverName = receiverName; this.deliveryAddress = deliveryAddress; this.weight = weight; this.shippingType = shippingType; } public CargoBuilder setDeliveryDayCommitment(int deliveryDayCommitment) { this.deliveryDayCommitment = deliveryDayCommitment; return this; } public CargoBuilder setDescription(String description) { this.description = description; return this; } public CargoBuilder setRegion(int region) { this.region = region; return this; } public Cargo build() { Cargo cargo = new Cargo(this); if ((ShippingType.DOMESTIC == cargo.getShippingType()) && (cargo.getRegion() <= 0 || cargo.getRegion() > 4)) { throw new IllegalStateException("Region is invalid! Cargo Tracking Id : " + cargo.getTrackingId()); } return cargo; } } STEP 3 : Cargo Message CargoMessage is the parent class of Domestic and International Cargo Messages. public class CargoMessage { private final Cargo cargo; public CargoMessage(Cargo cargo) { this.cargo = cargo; } public Cargo getCargo() { return cargo; } @Override public String toString() { return cargo.toString(); } } STEP 4 : Domestic Cargo Message DomesticCargoMessage Class models domestic cargo messages. public class DomesticCargoMessage extends CargoMessage { public enum Region { NORTH(1), SOUTH(2), EAST(3), WEST(4); private int value; private Region(int value) { this.value = value; } public static Region fromValue(int value) { return Arrays.stream(Region.values()) .filter(region -> region.value == value) .findFirst() .get(); } } private final Region region; public DomesticCargoMessage(Cargo cargo, Region region) { super(cargo); this.region = region; } public Region getRegion() { return region; } @Override public String toString() { return "DomesticCargoMessage [cargo=" + super.toString() + ", region=" + region + "]"; } } STEP 5 : International Cargo Message InternationalCargoMessage Class models international cargo messages. public class InternationalCargoMessage extends CargoMessage { public enum DeliveryOption { NEXT_FLIGHT, PRIORITY, ECONOMY, STANDART } private final DeliveryOption deliveryOption; public InternationalCargoMessage(Cargo cargo, DeliveryOption deliveryOption) { super(cargo); this.deliveryOption = deliveryOption; } public DeliveryOption getDeliveryOption() { return deliveryOption; } @Override public String toString() { return "InternationalCargoMessage [cargo=" + super.toString() + ", deliveryOption=" + deliveryOption + "]"; } } STEP 6 : Application Configuration AppConfiguration is configuration provider class for Spring Container. It creates Message Channels and registers to Spring BeanFactory. Also @EnableIntegration enables imported spring integration configuration and @IntegrationComponentScan scans Spring Integration specific components. Both of them came with Spring Integration 4.0. import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.integration.annotation.IntegrationComponentScan; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.config.EnableIntegration; import org.springframework.messaging.MessageChannel; @Configuration @ComponentScan("com.onlinetechvision.integration") @EnableIntegration @IntegrationComponentScan("com.onlinetechvision.integration") public class AppConfiguration { /** * Creates a new cargoGWDefaultRequest Channel and registers to BeanFactory. * * @return direct channel */ @Bean public MessageChannel cargoGWDefaultRequestChannel() { return new DirectChannel(); } /** * Creates a new cargoSplitterOutput Channel and registers to BeanFactory. * * @return direct channel */ @Bean public MessageChannel cargoSplitterOutputChannel() { return new DirectChannel(); } /** * Creates a new cargoFilterOutput Channel and registers to BeanFactory. * * @return direct channel */ @Bean public MessageChannel cargoFilterOutputChannel() { return new DirectChannel(); } /** * Creates a new cargoRouterDomesticOutput Channel and registers to BeanFactory. * * @return direct channel */ @Bean public MessageChannel cargoRouterDomesticOutputChannel() { return new DirectChannel(); } /** * Creates a new cargoRouterInternationalOutput Channel and registers to BeanFactory. * * @return direct channel */ @Bean public MessageChannel cargoRouterInternationalOutputChannel() { return new DirectChannel(); } /** * Creates a new cargoTransformerOutput Channel and registers to BeanFactory. * * @return direct channel */ @Bean public MessageChannel cargoTransformerOutputChannel() { return new DirectChannel(); } } STEP 7 : Messaging Gateway CargoGateway Interface exposes domain-specific method to the application. In other words, it provides an application access to the messaging system. Also @MessagingGateway came with Spring Integration 4.0 and simplifies gateway creation in messaging system. Its default request channel is cargoGWDefaultRequestChannel. import java.util.List; import org.springframework.integration.annotation.Gateway; import org.springframework.integration.annotation.MessagingGateway; import org.springframework.messaging.Message; import com.onlinetechvision.model.Cargo; @MessagingGateway(name = "cargoGateway", defaultRequestChannel = "cargoGWDefaultRequestChannel") public interface ICargoGateway { /** * Processes Cargo Request * * @param message SI Message covering Cargo List payload and Batch Cargo Id header. * @return operation result */ @Gateway void processCargoRequest(Message> message); } STEP 8 : Messaging Splitter CargoSplitter listens cargoGWDefaultRequestChannel channel and breaks incoming Cargo List into Cargo messages. Cargo messages are sent to cargoSplitterOutputChannel. import java.util.List; import org.springframework.integration.annotation.MessageEndpoint; import org.springframework.integration.annotation.Splitter; import org.springframework.messaging.Message; import com.onlinetechvision.model.Cargo; @MessageEndpoint public class CargoSplitter { /** * Splits Cargo List to Cargo message(s) * * @param message SI Message covering Cargo List payload and Batch Cargo Id header. * @return cargo list */ @Splitter(inputChannel = "cargoGWDefaultRequestChannel", outputChannel = "cargoSplitterOutputChannel") public List splitCargoList(Message> message) { return message.getPayload(); } } STEP 9 : Messaging Filter CargoFilter determines whether the message should be passed to the message channel. It listens cargoSplitterOutputChannel channel and filters cargo messages exceeding weight limit. If Cargo message is lower than weight limit, it is sent to cargoFilterOutputChannelchannel. If Cargo message is higher than weight limit, it is sent to cargoFilterDiscardChannelchannel. import org.springframework.integration.annotation.Filter; import org.springframework.integration.annotation.MessageEndpoint; import com.onlinetechvision.model.Cargo; @MessageEndpoint public class CargoFilter { private static final long CARGO_WEIGHT_LIMIT = 1_000; /** * Checks weight of cargo and filters if it exceeds limit. * * @param Cargo message * @return check result */ @Filter(inputChannel="cargoSplitterOutputChannel", outputChannel="cargoFilterOutputChannel", discardChannel="cargoFilterDiscardChannel") public boolean filterIfCargoWeightExceedsLimit(Cargo cargo) { return cargo.getWeight() <= CARGO_WEIGHT_LIMIT; } } STEP 10 : Discarded Cargo Message Listener DiscardedCargoMessageListener listens cargoFilterDiscard Channel and handles Cargo messages discarded by CargoFilter. import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.integration.annotation.MessageEndpoint; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.messaging.handler.annotation.Header; import com.onlinetechvision.model.Cargo; @MessageEndpoint public class DiscardedCargoMessageListener { private final Logger logger = LoggerFactory.getLogger(DiscardedCargoMessageListener.class); /** * Handles discarded domestic and international cargo request(s) and logs. * * @param cargo domestic/international cargo message * @param batchId message header shows cargo batch id */ @ServiceActivator(inputChannel = "cargoFilterDiscardChannel") public void handleDiscardedCargo(Cargo cargo, @Header("CARGO_BATCH_ID") long batchId) { logger.debug("Message in Batch[" + batchId + "] is received with Discarded payload : " + cargo); } } STEP 11 : Messaging Router CargoRouter determines what channel(s) should receive the message next if it is available. It listens cargoFilterOutputChannel channel and returns related channel name in the light of cargo shipping type. In other words, it routes incoming cargo messages to domestic(cargoRouterDomesticOutputChannel) or international(cargoRouterInternationalOutputChannel) cargo channels. Also if shipping type is not set, nullChannel is returned. nullChannel is a dummy message channel to be used mainly for testing and debugging. It does not send the message from sender to receiver but its send method always returns true and receive method returns null value. import org.springframework.integration.annotation.MessageEndpoint; import org.springframework.integration.annotation.Router; import com.onlinetechvision.model.Cargo; import com.onlinetechvision.model.Cargo.ShippingType; @MessageEndpoint public class CargoRouter { /** * Determines cargo request' s channel in the light of shipping type. * * @param Cargo message * @return channel name */ @Router(inputChannel="cargoFilterOutputChannel") public String route(Cargo cargo) { if(cargo.getShippingType() == ShippingType.DOMESTIC) { return "cargoRouterDomesticOutputChannel"; } else if(cargo.getShippingType() == ShippingType.INTERNATIONAL) { return "cargoRouterInternationalOutputChannel"; } return "nullChannel"; } } STEP 12 : Messaging Transformer CargoTransformer listens cargoRouterDomesticOutputChannel &cargoRouterInternationalOutputChannel and transforms incoming Cargo requests to Domestic and International Cargo messages. After then, it sends them tocargoTransformerOutputChannel channel. import org.springframework.integration.annotation.MessageEndpoint; import org.springframework.integration.annotation.Transformer; import com.onlinetechvision.model.Cargo; import com.onlinetechvision.model.DomesticCargoMessage; import com.onlinetechvision.model.DomesticCargoMessage.Region; import com.onlinetechvision.model.InternationalCargoMessage; import com.onlinetechvision.model.InternationalCargoMessage.DeliveryOption; @MessageEndpoint public class CargoTransformer { /** * Transforms Cargo request to Domestic Cargo obj. * * @param cargo * request * @return Domestic Cargo obj */ @Transformer(inputChannel = "cargoRouterDomesticOutputChannel", outputChannel = "cargoTransformerOutputChannel") public DomesticCargoMessage transformDomesticCargo(Cargo cargo) { return new DomesticCargoMessage(cargo, Region.fromValue(cargo.getRegion())); } /** * Transforms Cargo request to International Cargo obj. * * @param cargo * request * @return International Cargo obj */ @Transformer(inputChannel = "cargoRouterInternationalOutputChannel", outputChannel = "cargoTransformerOutputChannel") public InternationalCargoMessage transformInternationalCargo(Cargo cargo) { return new InternationalCargoMessage(cargo, getDeliveryOption(cargo.getDeliveryDayCommitment())); } /** * Get delivery option by delivery day commitment. * * @param deliveryDayCommitment delivery day commitment * @return delivery option */ private DeliveryOption getDeliveryOption(int deliveryDayCommitment) { if (deliveryDayCommitment == 1) { return DeliveryOption.NEXT_FLIGHT; } else if (deliveryDayCommitment == 2) { return DeliveryOption.PRIORITY; } else if (deliveryDayCommitment > 2 && deliveryDayCommitment < 5) { return DeliveryOption.ECONOMY; } else { return DeliveryOption.STANDART; } } } STEP 13 : Messaging Service Activator CargoServiceActivator is a generic endpoint for connecting service instance to the messaging system. It listens cargoTransformerOutputChannel channel and gets processed domestic and international cargo messages and logs. import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.integration.annotation.MessageEndpoint; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.messaging.handler.annotation.Header; import com.onlinetechvision.model.CargoMessage; @MessageEndpoint public class CargoServiceActivator { private final Logger logger = LoggerFactory.getLogger(CargoServiceActivator.class); /** * Gets processed domestic and international cargo request(s) and logs. * * @param cargoMessage domestic/international cargo message * @param batchId message header shows cargo batch id */ @ServiceActivator(inputChannel = "cargoTransformerOutputChannel") public void getCargo(CargoMessage cargoMessage, @Header("CARGO_BATCH_ID") long batchId) { logger.debug("Message in Batch[" + batchId + "] is received with payload : " + cargoMessage); } } STEP 14 : Application Application Class is created to run the application. It initializes application context and sends cargo requests to messaging system. import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.messaging.support.MessageBuilder; import com.onlinetechvision.integration.ICargoGateway; import com.onlinetechvision.model.Cargo; import com.onlinetechvision.model.Cargo.ShippingType; public class Application { public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfiguration.class); ICargoGateway orderGateway = ctx.getBean(ICargoGateway.class); getCargoBatchMap().forEach( (batchId, cargoList) -> orderGateway.processCargoRequest(MessageBuilder .withPayload(cargoList) .setHeader("CARGO_BATCH_ID", batchId) .build())); } /** * Creates a sample cargo batch map covering multiple batches and returns. * * @return cargo batch map */ private static Map> getCargoBatchMap() { Map> cargoBatchMap = new HashMap<>(); cargoBatchMap.put(1, Arrays.asList( new Cargo.CargoBuilder(1, "Receiver_Name1", "Address1", 0.5, ShippingType.DOMESTIC) .setRegion(1).setDescription("Radio").build(), //Second cargo is filtered due to weight limit new Cargo.CargoBuilder(2, "Receiver_Name2", "Address2", 2_000, ShippingType.INTERNATIONAL) .setDeliveryDayCommitment(3).setDescription("Furniture").build(), new Cargo.CargoBuilder(3, "Receiver_Name3", "Address3", 5, ShippingType.INTERNATIONAL) .setDeliveryDayCommitment(2).setDescription("TV").build(), //Fourth cargo is not processed due to no shipping type found new Cargo.CargoBuilder(4, "Receiver_Name4", "Address4", 8, null) .setDeliveryDayCommitment(2).setDescription("Chair").build())); cargoBatchMap.put(2, Arrays.asList( //Fifth cargo is filtered due to weight limit new Cargo.CargoBuilder(5, "Receiver_Name5", "Address5", 1_200, ShippingType.DOMESTIC) .setRegion(2).setDescription("Refrigerator").build(), new Cargo.CargoBuilder(6, "Receiver_Name6", "Address6", 20, ShippingType.DOMESTIC) .setRegion(3).setDescription("Table").build(), //Seventh cargo is not processed due to no shipping type found new Cargo.CargoBuilder(7, "Receiver_Name7", "Address7", 5, null) .setDeliveryDayCommitment(1).setDescription("TV").build())); cargoBatchMap.put(3, Arrays.asList( new Cargo.CargoBuilder(8, "Receiver_Name8", "Address8", 200, ShippingType.DOMESTIC) .setRegion(2).setDescription("Washing Machine").build(), new Cargo.CargoBuilder(9, "Receiver_Name9", "Address9", 4.75, ShippingType.INTERNATIONAL) .setDeliveryDayCommitment(1).setDescription("Document").build())); return Collections.unmodifiableMap(cargoBatchMap); } } STEP 15 : Build Project Cargo requests’ operational results are as follows : Cargo 1 : is sent to service activator successfully. Cargo 2 : is filtered due to weight limit. Cargo 3 : is sent to service activator successfully. Cargo 4 : is not processed due to no shipping type. Cargo 5 : is filtered due to weight limit. Cargo 6 : is sent to service activator successfully. Cargo 7 : is not processed due to no shipping type. Cargo 8 : is sent to service activator successfully. Cargo 9 : is sent to service activator successfully. After the project is built and run, the following console output logs will be seen : 2014-12-09 23:43:51 [main] DEBUG c.o.i.CargoServiceActivator - Message in Batch[1] is received with payload : DomesticCargoMessage [cargo=Cargo [trackingId=1, receiverName=Receiver_Name1, deliveryAddress=Address1, weight=0.5, description=Radio, shippingType=DOMESTIC, deliveryDayCommitment=0, region=1], region=NORTH] 2014-12-09 23:43:51 [main] DEBUG c.o.i.DiscardedCargoMessageListener - Message in Batch[1] is received with Discarded payload : Cargo [trackingId=2, receiverName=Receiver_Name2, deliveryAddress=Address2, weight=2000.0, description=Furniture, shippingType=INTERNATIONAL, deliveryDayCommitment=3, region=0] 2014-12-09 23:43:51 [main] DEBUG c.o.i.CargoServiceActivator - Message in Batch[1] is received with payload : InternationalCargoMessage [cargo=Cargo [trackingId=3, receiverName=Receiver_Name3, deliveryAddress=Address3, weight=5.0, description=TV, shippingType=INTERNATIONAL, deliveryDayCommitment=2, region=0], deliveryOption=PRIORITY] 2014-12-09 23:43:51 [main] DEBUG c.o.i.DiscardedCargoMessageListener - Message in Batch[2] is received with Discarded payload : Cargo [trackingId=5, receiverName=Receiver_Name5, deliveryAddress=Address5, weight=1200.0, description=Refrigerator, shippingType=DOMESTIC, deliveryDayCommitment=0, region=2] 2014-12-09 23:43:51 [main] DEBUG c.o.i.CargoServiceActivator - Message in Batch[2] is received with payload : DomesticCargoMessage [cargo=Cargo [trackingId=6, receiverName=Receiver_Name6, deliveryAddress=Address6, weight=20.0, description=Table, shippingType=DOMESTIC, deliveryDayCommitment=0, region=3], region=EAST] 2014-12-09 23:43:51 [main] DEBUG c.o.i.CargoServiceActivator - Message in Batch[3] is received with payload : DomesticCargoMessage [cargo=Cargo [trackingId=8, receiverName=Receiver_Name8, deliveryAddress=Address8, weight=200.0, description=Washing Machine, shippingType=DOMESTIC, deliveryDayCommitment=0, region=2], region=SOUTH] 2014-12-09 23:43:51 [main] DEBUG c.o.i.CargoServiceActivator - Message in Batch[3] is received with payload : InternationalCargoMessage [cargo=Cargo [trackingId=9, receiverName=Receiver_Name9, deliveryAddress=Address9, weight=4.75, description=Document, shippingType=INTERNATIONAL, deliveryDayCommitment=1, region=0], deliveryOption=NEXT_FLIGHT] Source Code Source Code is available on Github References Enterprise Integration Patterns Spring Integration Reference Manual Spring Integration 4.1.0.RELEASE API Pro Spring Integration Spring Integration 3.0.2 and 4.0 Milestone 4 Released
December 18, 2014
by Eren Avsarogullari
· 154,652 Views · 9 Likes
article thumbnail
AWS Activate: Pros, Cons, and Everything in Between
First and foremost, it is important to define what AWS Activate is and what it is used for before we can take a deeper look. Exactly one year ago, Amazon created a program specifically designed for a particular group of customers that often times is in need of as much help as they can get (AKA startups). This program supports startups in their initial phase of building their businesses. This includes providing AWS credits, taking part in startup contests, and receiving benefits from third party solutions on the AWS cloud. Activate allows AWS partners that want to create a presence within the Activate community offer perks to member startups. Some of which include discounts and extended free tiers. Some startups that have attained high levels of success with AWS include Spotify, Pinterest, and Dropbox. With the big shots maintaining their places in startup stardom, Amazon has opened its doors to the next generation of innovators. As such, Amazon offers two different Activate packages. The Self-Starter package is comprised of a limited amount of each of the offerings listed above, whereas the Portfolio package includes some added bonuses along the lines of more high-profile and technical support as well as more in-depth training. On his blog AWS’ CTO, Werner Vogel, reiterated the importance of startups, “Startups will forever be a very important customer segment of AWS. They were among our first customers and along the way some amazing businesses have been built by these startups, many of which running for 100% on AWS.” “We’re excited to be a part of this global momentum in the startup ecosystem. The challenge now is to support and assist an increasing number of startups across the world.” The fun doesn’t stop there. In April of this year, AWS expanded the Activate package to offer much more than generalupport. This entailed sponsoring solution architects to take startups through step by step consultations in the fields of security, architecture and performance. Consequently, though Amazon’s professional services teams were established for customers, it was natural to have them take part in Activate. By nurturing new startups and making them rely heavily on the AWS cloud. As we can see today, companies that started with AWS 4 years ago are now worth billions of dollars. Airbnb and Dropbox, for example, now thoroughly enjoy the flexibility Amazon offers, as well as the fact that they no longer have to maintain cumbersome IT operations. Why not from the get-go? So the question is, if Amazon essentially built AWS on startups, why hasn’t Activate been around from the get-go, 6 years ago? AWS owes a great deal of its success to scalable startups that wanted and needed servers to run their businesses, yet didn’t have the initial capital to build their own data centers. No one really knows why Amazon did not provide startups back then with the kind of support they do today. However, as the market matured, it became clear that Amazon realized that an increasing number of startups could use their help. As a result, Amazon discovered that marketing their support services through Venture Capitalists and incubators around the world would include them as partners in this program and aid in marketing the service to startups of all kinds. “AWS Activate requires a special registration that allows startup customers with a valid AWS account to apply for either a self-starter package or a portfolio package. If a startup is a member of one of the accelerators, seed funds, or startup organizations that Amazon already works with, they may apply for the more exclusive AWS Activate Portfolio Package.” Learn More Incubators and Accelerators It was a natural step for Amazon to partner with accelerators all over the world with the Activate package. In addition to supporting startups, as mentioned above, these accelerators act as channels in the startup scene.At the first AWS re:Invent, Bezos jokes to his fellow investors, saying that eventually some of the investments will return to him because of how heavily the startup scene relies on Amazon. Activate and the approximately 150 accelerators across the world, including White Accel, Techstars, Appwest, and Battery Ventures, genuinely support and understand the values of the AWS service. They are happy to be able to use the Activate platform to help their startups flourish within the AWS clouds. 3rd Party Partners Aside from the accelerators, as an Amazon partner, you can enroll special offers to Activate members. For example, members that are part of the Self-Starter package may receive a 3 month free trial for Chef, whereas Portfolio members may receive a 6 month trial. Most of the partners will provide an extended free trial or credits via Activate. For instance, Trend Micro, one of Amazon’s biggest partners in the security domain, provides $2500 credit for Activate members in the Portfolio package. While there are not many partners on the list, the ones that are mentioned are very helpful and provide nice benefits for Activate members. Reviews of the program from both the partners’ and startups’ side showed that Activate is ideal for startups that have resource constraints. While members within the Self-Starter package are able to use the AWS Free Usage Tier, Portfolio members can receive anywhere from $1,000 to $15,000 in AWS Promotional Credit. The credit is maybe the most important value for these startups. Bearing in mind that Google also has their own line of packages and credit for new companies, it makes sense for AWS to start giving more life to these companies, above the free tier. Everyone has access to the free tier, these startups simply get more of it. Seems that there is no downside to participating. There is no obligation and the worst thing that can happen is that you will find that the services are great, and simply continue using them, which may result in you being locked-in to the point where you need to eventually pay. On the other hand, seems that the last announcement in April, which is actually “meet our architects”. Meaning the knowledge that Amazon’s architects share with startups in their consultation sessions help them get a better grasp on the ecosystem, as well as understand that more resource utilization is ultimately the next logical step for growth. All in all, although Amazon didn’t offer with this program 4 years ago, the AWS cloud was still the natural choice for startups. It included all of the benefits a startup can get using and online and on-demand infinite amount of resources. As a result, it is the clear choice for web scale startups. There are many reasons why Amazon only recently decided to offer free benefits to their prized potential customers. While it could have stemmed from competition from Microsoft and Google, or Amazon may want to simply show their support for their potential customers, demonstrating their cloud’s benefits at an early stage. Aside from that, Amazon understands and is built on companies with long term goals and possibilities. Therefore Amazon sees startups as a long term investment, which starts off with little risk.
December 15, 2014
by Ofir Nachmani
· 10,580 Views
article thumbnail
XAML and Converters Chaining
Converters are an essential building block in XAML interfaces with one simple task: converting values of one type to another. Since they have a input, usually a view model property, and an output, it would be wonderful if we could somehow chain them to create a new converter that processes all internal converters. Luckily, this is quite simple to do, but we do need to create a new converter which will hold other converters and whose implementation will iterate over nested converters. Full code can be found over at Github repository here, only interesting parts will be highlighted in this blog post. Our combining converter class is also a converter itself, but it can contain other converters inside it: [ContentProperty("Converters")] public class ChainingConverter : IValueConverter { public Collection Converters { get; set; } } Converter functions are trivially implemented and iteratively go through the converters list and apply the converter on the previous value. public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { foreach (var converter in Converters) { value = converter.Convert(value, targetType, parameter, culture); } return value; } ConvertBack is implemented in the same fashion. This allows us to create new converters in XAML with the following syntax: But what if we need to send parameters to some of the converters, how can we do that when the same parameter is used throughout the ChainingConverter implementation? To provide custom parameter for individual converters, we can create a wrapper converter around existing converter and specify parameter on that wrapper. Here is a skeleton for such wrapper converter, notice that the wrapper is also a converter: [ContentProperty("Converter")] public class ParameterizedConverterWrapper : DependencyObject, IValueConverter { // IValueConverter Converter dependency property // object Parameter dependency property // object DefaultReturnValue dependency property public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (Converter != null) return Converter.Convert(value, targetType, Parameter ?? parameter, culture); return DefaultReturnValue; } } Converter wrappers allow us to create complex converters such as this one: The final converter should be self explanatory even though you probably haven’t seen these converters before. You can see that unlike other converters, the wrapper is a dependency object which allows us to use bindings on the Parameter property since it is in fact a dependency property. More complex converters should be created from ordinary converters whenever possible, especially when working with primitive types such as bool, string, enums and null values. What’s next? The last example looked like a small DSL embedded in XAML. We could create converters that simulate flow control or conditionals. We could even create converters that switch depending on the property before it, essentially coding logic inside such converters. Whether that is desirable is debatable, but it can be done. The full code with sample application can be found at the following Github repository: MassivePixel/wp-common.
December 15, 2014
by Toni Petrina
· 5,267 Views
article thumbnail
An Introduction to BDD Test Automation with Serenity and JUnit
serenity bdd (previously known as thucydides ) is an open source reporting library that helps you write better structured, more maintainable automated acceptance criteria, and also produces rich meaningful test reports (or "living documentation") that not only report on the test results, but also what features have been tested. and for when your automated acceptance tests exercise a web interface, serenity comes with a host of features that make writing your automated web tests easier and faster. 1. bdd fundamentals but before we get into the nitty-gritty details, let’s talk about behaviour driven development, which is a core concept underlying many of serenity’s features. behaviour driven development, or bdd, is an approach where teams use conversations around concrete examples to build up a shared understanding of the features they are supposed to build. for example, suppose you are building a site where artists and craftspeople can sell their good online. one important feature for such a site would be the search feature. you might express this feature using a story-card format commonly used in agile projects like this: in order for buyers to find what they are looking for more efficiently as a seller i want buyers to be able to search for articles by keywords to build up a shared understanding of this requirement, you could talk through a few concrete examples. the converstaion might go something like this: "so give me an example of how a search might work." "well, if i search for wool , then i should see only woolen products." "sound’s simple enough. are there any other variations on the search feature that would produce different outcomes?" "well, i could also filter the search results; for example, i could look for only handmade woolen products." and so on. in practice, many of the examples that get discussed become "acceptance criteria" for the features. and many of these acceptance criteria become automated acceptance tests. automating acceptence tests provides valuable feedback to the whole team, as these tests, unlike unit and integrationt tests, are typically expressed in business terms, and can be easily understood by non-developers. and, as we will se later on in this article, the reports that are produced when these teste are executed give a clear picture of the state of the application. 2. serenity bdd and junit in this article, we will learn how to use serenity bdd using nothing more than junit, serenity bdd, and a little selenium webdriver. automated acceptance tests can use more specialized bdd tools such as cucumber or jbehave, but many teams like to keep it simple, and use more conventional unit testing tools like junit. this is fine: the essence of the bdd approach lies in the conversations that the teams have to discuss the requirements and discover the acceptance criteria. 2.1. writing the acceptance test let’s start off with a simple example. the first example that was discussed was searching for wool . the corresponding automated acceptance test for this example in junit looks like this: @runwith(serenityrunner.class) public class whensearchingbykeyword { @managed(driver="chrome", uniquesession = true) webdriver driver; @steps buyersteps buyer; @test public void should_see_a_list_of_items_related_to_the_specified_keyword() { // given buyer.opens_etsy_home_page(); // when buyer.searches_for_items_containing("wool"); // then. buyer.should_see_items_related_to("wool"); } } the serenity test runner sets up the test and records the test results this is a web test, and serenity will manage the webdriver driver for us we hide implementation details about how the test will be executed in a "step library" our test itself is reduced to the bare essential business logic that we want to demonstrate there are several things to point out here. when you use serenity with junit, you need to use the serenityrunner test runner. this instruments the junit class and instantiates the webdriver driver (if it is a web test), as well as any step libraries and page objects that you use in your test (more on these later). the @managed annotation tells serenity that this is a web test. serenity takes care of instantiating the webdriver instance, opening the browser, and shutting it down at the end of the test. you can also use this annotation to specify what browser you want to use, or if you want to keep the browser open during all of the tests in this test case. the @steps annotation tells serenity that this variable is a step library. in serenity, we use step libraries to add a layer of abstraction between the "what" and the "how" of our acceptance tests. at the top level, the step methods document "what" the acceptance test is doing, in fairly implementation-neutral, business-friendly terms. so we say "searches for items containing wool ", not "enters wool into the search field and clicks on the search button". this layered approach makes the tests both easier to understand and to maintain, and helps build up a great library of reusable business-level steps that we can use in other tests. 2.2. the step library the step library class is just an ordinary java class, with methods annotated with the @step annotation: public class buyersteps { homepage homepage; searchresultspage searchresultspage; @step public void opens_etsy_home_page() { homepage.open(); } @step public void searches_for_items_containing(string keywords) { homepage.searchfor(keywords); } @step public void should_see_items_related_to(string keywords) { list resulttitles = searchresultspage.getresulttitles(); resulttitles.stream().foreach(title -> assertthat(title.contains(keywords))); } } //end:tail step libraries often use page objects, which are automatically instantiated the @step annotation indicates a method that will appear as a step in the test reports for automated web tests, the step library methods do not call webdriver directly, but rather they typically interact with page objects . 2.3. the page objects page objects encapsulate how a test interacts with a particular web page. they hide the webdriver implementation details about how elements on a page are accessed and manipulated behind more business-friendly methods. like steps, page objects are reusable components that make the tests easier to understand and to maintain. serenity automatically instantiates page objects for you, and injects the current webdriver instance. all you need to worry about is the webdriver code that interacts with the page. and serenity provides a few shortcuts to make this easier as well. for example, here is the page object for the home page: @defaulturl("http://www.etsy.com") public class homepage extends pageobject { @findby(css = "button[value='search']") webelement searchbutton; public void searchfor(string keywords) { $("#search-query").sendkeys(keywords); searchbutton.click(); } } what url should be used by default when we call the open() method a serenity page object must extend the pageobject class you can use the $ method to access elements directly using css or xpath expressions or you may use a member variable annotated with the @findby annotation and here is the second page object we use: public class searchresultspage extends pageobject { @findby(css=".listing-card") list listingcards; public list getresulttitles() { return listingcards.stream() .map(element -> element.gettext()) .collect(collectors.tolist()); } } in both cases, we are hiding the webdriver implementation of how we access the page elements inside the page object methods. this makes the code both easier to read and reduces the places you need to change if a page is modified. this approach encourages a very high degree of reuse. for example, the second example mentioned at the start of this article involved filtering results by type. the corresponding automated acceptance criteria might look like this: @test public void should_be_able_to_filter_by_item_type() { // given buyer.opens_etsy_home_page(); // when buyer.searches_for_items_containing("wool"); int unfiltereditemcount = buyer.get_matching_item_count(); // and buyer.filters_results_by_type("handmade"); // then buyer.should_see_items_related_to("wool"); // and buyer.should_see_item_count(lessthan(unfiltereditemcount)); } @test public void should_be_able_to_view_details_about_a_searched_item() { // given buyer.opens_etsy_home_page(); // when buyer.searches_for_items_containing("wool"); buyer.selects_item_number(5); // then buyer.should_see_matching_details(); } notice how most of the methods here are reused from the previous steps: in fact, only two new methods are required. 3. reporting and living documentation reporting is one of serenity’s fortes. serenity not only reports on whether a test passes or fails, but documents what it did, in a step-by-step narrative format that inculdes test data and screenshots for web tests. for example, the following page illustrates the test results for our first acceptance criteria: figure 1. test results reported in serenity but test outcomes are only part of the picture. it is also important to know what work has been done, and what is work in progress. serenity provides the @pending annotation, that lets you indicate that a scenario is not yet completed, but has been scheduled for work, as illustrated here: @runwith(serenityrunner.class) public class whenputtingitemsintheshoppingcart { @pending @test public void shouldupdateshippingpricefordifferentdestinationcountries() { } } this test will appear in the reports as pending (blue in the graphs): figure 2. test result overview we can also organize our acceptance tests in terms of the features or requirements they are testing. one simple approach is to organize your requirements in suitably-named packages: |----net | |----serenity_bdd | | |----samples | | | |----etsy | | | | |----features | | | | | |----search | | | | | | |----whensearchingbykeyword.java | | | | | | |----whenviewingitemdetails.java | | | | | |----shopping_cart | | | | | | |----whenputtingitemsintheshoppingcart.java | | | | |----pages | | | | | |----homepage.java | | | | | |----itemdetailspage.java | | | | | |----registerpage.java | | | | | |----searchresultspage.java | | | | | |----shoppingcartpage.java | | | | |----steps | | | | | |----buyersteps.java all the test cases are organized under the features directory. test cass related to the search feature test cases related to the ‘shopping cart’ feature serenity can use this package structure to group and aggregate the test results for each feature. you need to tell serenity the root package that you are using, and what terms you use for your requirements. you do this in a special file called (for historical reasons) thucydides.properties , which lives in the root directory of your project: thucydides.test.root=net.serenity_bdd.samples.etsy.features thucydides.requirement.types=feature,story with this configured, serenity will report about how well each requirement has been tested, and will also tell you about the requirements that have not been tested: figure 3. serenity reports on requirements as well as tests 4. conclusion hopefully this will be enough to get you started with serenity. that said, we have barely scratched the surface of what serenity can do for your automated acceptance tests. you can read more about serenity, and the principles behind it, by reading the users manual , or by reading bdd in action , which devotes several chapters to these practices. and be sure to check out the online courses at parleys . you can get the source code for the project discussed in this article on github .
December 12, 2014
by John Ferguson Smart
· 59,892 Views · 6 Likes
  • Previous
  • ...
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • ...
  • 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
×