Oracle WebLogic Server 12.1.2, which is part of Oracle Cloud
Application Foundation, contains a number of exciting new capabilities, such as
support for RESTful services and HTML5 WebSockets. One of the features we’re most
excited about is what we call dynamic clusters. Dynamic clusters allow an
application to dynamically add servers on the fly. This used to have to be
manually preconfigured and now it’s automated, which offers a very elastic
environment for the applications we’ve been discussing. Also, Oracle WebLogic
Server 12.1.2 supports the new Oracle Database 12c release including its
multitenancy option, which is a significant capability for developing cloud
applications. Assuming that an application is providing software as a service [SaaS],
multitenancy means that each organization that’s purchasing that service has
its own secure set of data. Typically, it would be very expensive from an infrastructure
or management point of view to give each tenant its own database, but a true
multitenanted database capability is actually built into Oracle Database 12c.
Oracle WebLogic Server works very closely with the database to take advantage
of that capability, including taking advantage of what’s called Database
Resident Connection Pooling Purdy fuels up for the day with coffee and a
banana. IT’S COMPLICATED We need automation of management and simplification of
infrastructure and platform just to manage the complexity that is inherent [DRCP],
which is a serverside connection-pooling capability that significantly reduces
the number of physical connections necessary between a cluster of application
servers and a database cluster.
Sunday, 3 November 2013
Tuesday, 29 October 2013
More maps and reduction.
Maps and reduction are useful in a variety
of situations beyond just simple math. After all, in
any case where a collection of objects can be transformed into a different object
(or value) and then collected into a single value, map and reduction operations
work. The map operation, for example, can be useful as an extraction or projection
operation to take an object and extract portions of it, such as extracting the last
name out of a Person object: Once the last names
have been retrieved from the Person stream, the reduction can concatenate
strings together, such as transforming the last name into a data representation
for XML.
String xml =
"<people data='lastname'>" +
people.stream()
.map(it -> "<person>" + it.getLastName() +
"</person>")
.reduce("", String::concat)
+ "</people>";
System.out.println(xml);
And, naturally, if different XML formats are required, different operations
can be used to control the contents of each format, supplied either ad hoc, or from methods defined on other classes, such as from the Person class itself, which can then be used as part of the map() operation to transform the stream of Person objects into a JSON array
of object elements. The ternary operation in the middle of the reduce operation is there to avoid
putting a comma in front of the first Person serialized to JSON. Some
JSON parsers might accept this format, but that is not guaranteed, and it looks
ugly to have it there. It is ugly enough, in fact, to fix. The code is actually
a lot easier to write if we use the built-in Collector interface and its partner
Collectors, which specifically do
this kind of mutable-reduction operation .
This has the added benefit of
being much faster than the versions using the explicit reduce and String::concat from the earlier examples,
so it’s generally a better bet.Oh, and lest we forget our old friend Comparator, note that Stream also has an operation to
sort a stream in-flight, so the sorted JSON representation of the Person list looks like.This is
powerful stuff.
Parallelization.
What’s even more powerful is that these operations are entirely
independent of the logic necessary to pull each object through the Stream and act ion each one, which
means that the traditional for loop will break down when
attempting to iterate, map, or reduce a large collection by breaking the collection into segments that will each be processed by
a separate thread. The Stream API, however, already has
that covered, making the XML or JSON map() and reduce() operations shown earlier a slightly different operation—instead of calling stream() to obtain a Stream from the collection, use parallelStream() instead. For a collection
of at least a dozen items, at least on my laptop, two threads are used to
process the collection: the thread named main, which is the traditional
one used to invoke the main() method of a Java class, and
another thread named ForkJoinPool.commonPool worker-1, which is obviously not of
our creation.
Obviously, for a collection of a dozen items, this would be
hideously unnecessary, but for several hundred or more, this would be the
difference between “good enough” and “needs to go faster.” Without these new
methods and approaches, you would be staring at some significant code and algorithmic
study. With them, you can write parallelized code literally by adding eight keystrokes(nine if you count the Shift key
required
to capitalize the s in stream) to the previously sequential
processing. And, where necessary, a parallel Stream can be brought back to a
sequential one by calling—you can probably guess— sequential() on it.
The important thing to note
is that regardless of whether the processing is better done sequentially or in parallel, the same Stream interface is used for both. The sequential or parallel implementation becomes entirely
an implementation detail, which is exactly where we want it to be when working
on code that focuses on business needs (and value); we don’t want to focus on the
low-level details of firing up threads in thread pools and synchronizing across
them.
Friday, 25 October 2013
Additional changes in Collections in Java 8
With some additional APIs on the Collection classes themselves, a variety of new and more powerful approaches
and techniques open up, most often leveraging techniques drawn from the world of
functional programming. No knowledge of functional programming is necessary to use them,
fortunately, as long you can open your mind to the idea that functions are just
as valuable to manipulate and reuse as are classes and objects.
Comparisons. One of the drawbacks to the Comparator approach shown earlier is hidden inside the Comparator implementation. The code is actually doing two comparisons, one as a “dominant”
comparison
over the other, meaning that last names are compared first, and
age is compared only if the last names
are identical. If project requirements later demand that sorting be done by age
first and by last names second, a new Comparator must be written—no parts of compareLastAndAge can be reused. This is where taking a more functional approach can add
some powerful benefits. If we look at that comparison as entirely
separate Comparator instances, we can combine
them to create the precise kind of comparison needed. Historically, writing the combination by hand has been less productive, because by the time you write
the code to do the combination, it would be just as fast (if not faster) to
write the multistage comparison by hand. As a matter of fact, this “I want to
compare these two X things by comparing values
returned to me by a method on each X” approach is such a common
thing, the platform gave us that functionality out of the box. On the Comparator class, a comparing method takes a function (a
lambda) that extracts a comparison key out of the object and returns a Comparator that sorts based on that. The Person is no longer about sorting,
but just about extracting the key by which the sort should be done. This is a
good thing—Person shouldn’t have to think
about how to sort; Person should just focus on being a
Person. It gets better, though,
particularly when we want to compare based on two or more of those values.
Composition. As of Java 8, the Comparator interface comes with several methods to combine Comparator instances in various ways by stringing them together. For example, the Comparator .thenComparing() method takes a Comparator to use for comparison after the first one compares. So, re-creating the “last name then age” comparison can now be written in terms of the two Comparator instances LAST and AGE. Or, if you prefer to use
methods rather than Comparator instances . By the way, for
those who didn’t
grow up using Collections.sort(), there’s now a sort() method directly on List. This is one of the neat
things about the introduction of interface default methods: where we used to have to put that kind
of noninheritance-based reusable behavior in static methods, now it can be
hoisted up intointerfaces. Similarly, if the code needs to sort the collection
of Person objects by last name and
then by first name, no new Comparator needs to be written, because this comparison can, again, be made
of the two particular atomic comparisons as shown below.
Collections.sort(people,
Comparators.comparing(Person::getLastName)
.thenComparing(Person::getFirstName));
This combinatory “connection” of methods, known as functional composition, is common in functional programming
and at the heart of why functional programming is as powerful as it is. It’s
important to understand that the real benefit here isn’t just in the APIs that
enable us to do comparisons, but the ability to pass bits of executable code
(and then combine them in new and interesting ways) to create opportunities
for reuse and design. Comparator is just the tip of the iceberg. Lots of things can be made more flexible and powerful, particularly when combining and composing them.
Monday, 21 October 2013
Collections and Algorithms
The Collections API has been with us since JDK 1.2, but not all
parts of it have received equal attention or love from the developer community.
Algorithms, a more functional-centric way of interacting with collections,
have been a part of the Collections API since its initial release,
but they often get little attention, despite their usefulness. For example, the Collections class sports a dozen or so methods all designed to take a
collection as a parameter and perform some operation against the collection or its
contents. Consider, for example, the Person class
public class Person {
public Person(String fn, String ln, int a) {
this.firstName = fn; this.lastName = ln; this.age = a;
}
public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
public int getAge() { return age; }
}
which in turn is used by a List that holds a dozen or so Person objects. Now, assuming we
want to examine or sort this list by last name and then by age, a naive
approach is to write a for loop (in other words, implement
the sort by hand each time we need to sort). The problem with this, of course,
is that this violates DRY (the Don’t Repeat Yourself principle) and, worse, we have
to reimplement it each time, because for loops are not reusable. The Collections API has a better approach: the Collections class sports a sort method that will sort the
contents of the List. However, using this
requires the Person class to implement the Comparable method (which is called a natural ordering, and defines a default ordering for all Person types) or you have to pass
in a Comparator instance to define how Person objects should be sorted. So,
if we want to sort first by last name and then by age (in the event the last
names are the same . But that’s a lot of work to do something as simple as sort
by last name and then by age. This is exactly where the new closures feature
will be of help, making it easier to write the Comparator .The Comparator is a prime example of the need
for lambdas in the language: it’s one of the dozens of places where a one-off
anonymous method is useful. (Bear in mind, this is probably the easiest—and weakest—benefit of lambdas. We’re essentially
trading one syntax for another, admittedly terser, syntax, but even if you put this
article down and walk away right now, a significant amount of code will be saved just from that terseness.) If this particular comparison is
something that we use over time, we can always capture the lambda as a Comparator instance, because that is
the signature of the method—in this case, "int compare(Person, Person)"—that the lambda fits, and store it on the Person class directly, making the implementation
of the lambda and its use
even more readable . Storing a Comparator<Person> instance on the Person class is a bit odd, though.
It would make more sense to define a method that does the comparison, and use that instead of a Comparator instance. Fortunately, Java
will allow any method to be used that satisfies the same signature as the method on Comparator, so it’s equally possible to write the BY_LAST_ AND_AGE Comparator as a standard instance or static method on Person and use it instead . Thus,
even without any changes to the Collections API, lambdas are already helpful and useful. Again, if you walk away from this article right here,
things are
pretty good. But they’re about to get a lot better.
Tuesday, 15 October 2013
Applications for Websocket
The
Java EE 7 specification adds new functionality to the Java EE specification. One
capability many developers were asking for is support for WebSockets. Real-time
bidirectional traffic on the internet is growing. Different actors are involved
in this area, including content providers, broadcasters, software developers,
and telecom operators. Due to the different characteristics of the involved
actors, the success of WebSockets required
standardization. The Internet Engineering Task Force (IETF) defined a standard
for the WebSocket protocol. This standard defines
the low-level protocol that technologies implementing WebSockets should adhere
to. For example, it defines how an HTTP connection should
be upgraded to a full-duplex bidirectional WebSocket connection. The importance
of this standard cannot be underestimated. Different languages and platforms are
used to develop applications relying on WebSockets,
and they should all rely on the same protocol in order to be interoperable. On
top of the WebSocket protocol, a number of technologies and
implementations exist facilitating the use of WebSockets in a specific language
or platform. For example, the W3C has a working draft describing how
to leverage WebSockets from a web page, and ever since Java EE 7, a similar specification
has existed for dealing with WebSockets in Java. This specification is defined
in JSR 356 and was approved to be part of the Java
EE 7 specification. The Java API for WebSocket contains a server API and a client
API. Containers that claim to be Java EE 7– compliant implement the server API.
The only real difference between a server container
and a client container is that a server container provides the infrastructure for
registering WebSocket endpoints—it will listen for incoming requests on
specific endpoints. The client API is, therefore, a subset of the server API. The
Reference Implementation for JSR 356, named Tyrus, is included in GlassFish 4
and contains client modules as well as server modules. The client modules can
be used in any Java
application and allow developers to connect to any WebSocket endpoint, as long as
the endpoint adheres to the IETF 6455 standard. On top
of the client modules, the server modules allow applications to register
endpoints that will handle all WebSocket communications, as long as the other peer
(the client) adheres to the IETF 6455 standard.
Monday, 14 October 2013
How developer's are using the cloud
Several
improvements in Java EE 7 are relevant. Obviously, the new batch specification,
JSR 352, is tremendously valuable, and not only for cloud computing. It’s able
to take significant amounts of work that might otherwise have to be done
synchronously and break it down into smaller units and perform those asynchronously.
In addition, the Java EE role definitions have been updated to better map to
the security requirements we
see in cloud environments, such as the difference between someone administering
platform as a service [PaaS], on which the application is running, versus administering
the application itself that is being hosted. Software
also works better in a cloud environment when we get rid of certain
assumptions. One way to do this is through dependency injection, which was introduced
in Java EE 5 and, as of Java EE 7, now applies across the entire Java set of
enterprise specifications and is called Context and
Dependency Injection [CDI]. Instead of going out and finding what you need as a
component, you simply declare what you need. If you need to connect to a
database, the component declares that it needs to be connected to a database
and then it allows whatever environment it’s running in to provide it with a
connection to that database based on how that environment is configured. IaaS
manages the requisite networking and server hardware, and it typically hosts
virtual machines, each of which is running an operating system—all of which is below
the level of Java EE. We imagine that every data center, every private cloud,
and every public cloud will be providing IaaS: infrastructure services that
platforms and applications can take advantage of through standardized IaaS
APIs. Generally speaking, what developers are looking for is PaaS. Developers
need to be able to describe
an application hosting environment: an application server or a cluster
of application servers, which are often combined with a database. And
they need to have their application exposed to the real world, protected by a
firewall, and automatically balanced by a load balancer. In
other words, they’re not interested in building or installing their own
firewall, load balancer, or database. They want to be able to take an
application, including necessary components and their database design, and
deploy it in a way that is accessible and secure. So, think of an application
that you’re deploying for a mobile platform; it’s probably going to
consist of a significant number of RESTful interfaces that are exposed to
a mobile platform. Those RESTful interfaces will be exposed through a
URL that will come to a load balancer that spreads requests across an elastically
scaled application server infrastructure, providing both high availability
and elastic scalability. The application servers will be running the application
logic, which will be transforming information from a database or other data
services into RESTful responses that are sent back to the mobile application
itself. All of the complexity of provisioning, configuring, monitoring, and
scaling the application infrastructure is provided and managed by PaaS.
Sunday, 13 October 2013
More focus on Clouds for Java developers
Let
us take the discussion started in the previous article posted to another
level and try to understand the exact
reason of why java developers focuss on Clouds. First, it’s important to
appreciate the wide scope of the term cloud
computing. Obviously, we talk about the public
cloud, including Amazon EC2 or Microsoft Azure, not to mention Oracle’s own
public cloud. But cloud computing is also changing the way that we manage
internal data centers —what we refer to as the private cloud. In other words, the very same
concepts, efficiencies, and capabilities that the public cloud brought us are
now available inside the data center—for example, basic tenets such as
self-service and being able to get a development, staging, or production
environment for an application in minutes—without going through any significant
paperwork or human workflow. On top of that, the elasticity of the cloud means that
we’re no longer constrained by a
one-size-fits-all
model. Applications must be built so that they can dynamically scale out and
dynamically balance the load across multiple servers.
This means that when servers are added while an application is
running,
there’s no interruption of service. To accomplish this, it’s good programming
practice to always assume that an application or the components of an
application are running in a scaled environment, which means
many previous assumptions no longer apply. I’m talking about things such as
file systems—which could be either local or shared and could trip up developers
either way—or global Java objects on the heap, which won’t actually be “global”
when the application is scaled out. Developers
must also understand whether the addition of resources will actually
enable an application to scale out effectively. In other words, just because
an application runs correctly when you add additional servers, that doesn’t
mean it will actually support more transactions or users. So, you need
to explicitly design into the scaleout model the ability for the application to
scale as close to linearly as possible. Obviously, data caching is a huge part
of this, as is minimizing the amount of information that has to be shared
across servers, as is minimizing contention
on
shared resources such as database systems. Finally, the application needs
to be understood in terms of the metrics of elasticity: when are additional resources
actually needed, and when is it safe for resources to be taken away? So, you
need to know when you need to scale out the application,
which involves knowing what to monitor.
Subscribe to:
Posts (Atom)