Immutable Data Structures in Java

As part of some of the coding interviews I’ve been conducting recently, the topic of immutability sometimes comes up. I’m not overly dogmatic in it myself, but whenever there’s no need for mutable state, I try to get rid of code which makes code mutable, which is often most visible in data structures. However, there seems to be a bit of a misunderstanding on the concept of immutability, where developers often believe that having a final reference, or val in Kotlin or Scala, is enough to make an object immutable. This blogpost dives a bit deeper in immutable references and immutable data structures.

Benefits of Immutable Data Structures

Immutable data structures have significant benefits, such as:

  • No invalid state
  • Thread safety
  • Easier-to-understand code
  • Easier-to-test code
  • Can be used for value types

No Invalid State

When an object is immutable, it’s hard to have the object in an invalid state. The object can only be instantiated through its constructor, which will enforce the validity of objects. This way, the required parameters for a valid state can be enforced. An example:

Address address = new Address();
address.setCity("Sydney");
// address is in invalid state now, since the country hasn’t been set.
Address address = new Address("Sydney", "Australia");
// Address is valid and doesn’t have setters, so the address object is always valid.

Thread Safety

Since the object cannot be changed, it can be shared between threads without having race conditions or data mutation issues.

Easier-to-Understand Code

Similar to the code example of the invalid state, it’s generally easier to use a constructor than initialization methods. This is because the constructor enforces the required arguments, while setter or initializer methods are not enforced at compile time.

Easier-to-Test Code

Since objects are more predictable, it’s not necessary to test all permutations of the initializer methods, i.e. when calling the constructor of a class, the object is either valid or invalid. Other parts of the code that are using these classes become more predictable, having fewer chances of NullPointerExceptions. Sometimes, when passing objects around, there are methods that could potentially mutate the state of the object. For example:

public boolean isOverseas(Address address) {
    if(address.getCountry().equals("Australia") == false) {
        address.setOverseas(true); // address has now been mutated!
        return true;
    } else {
        return false;
    }
}

The above code, in general, is bad practice. It returns a boolean as well as potentially changing the state of the object. This makes the code harder to understand and to test. A better solution would be to remove the setter from theAddress class, and return a boolean by testing for the country name. An even better way would be to move this logic to the Address class itself (address.isOverseas()). When state really needs to be set, make a copy of the original object without mutating the input.

Can Be Used for Value Types

Imagine a money amount, say 10 dollars. 10 dollars will always be 10 dollars. In code, this could look like  public Money(final BigInteger amount, final Currency currency). As you can see in this code, it’s not possible to change the value of 10 dollars to anything other than that, and thus, the above can be used safely for value types.

Final References Don’t Make Objects Immutable

As mentioned before, one of the issues I regularly encounter with developers is that a large portion of these developers don’t fully understand the difference between final references and immutable objects. It seems that the common understanding of these developers is that the moment a variable becomes final, the data structure becomes immutable. Unfortunately, it’s not that simple, and I’d like to get this misunderstanding out of the world once and for all:

A final reference does not make your objects immutable!

In other words, the following code does not make your objects immutable:

final Person person = new Person("John");

Why not? Well, whileperson is a final field and cannot be reassigned, the Person class might have a setter method or other mutator methods, making an action like:

person.setName("Cindy");

This is quite an easy thing to do, regardless of the final modifier. Alternatively, the Person class might expose a list of addresses like this. Accessing this list allows you to add an address to it and, therefore, mutate the person object like so:

person.getAddresses().add(new Address("Sydney"));

Our final reference again didn’t help us in stopping us from mutating the person object.

OK, now that we’ve got that out the way, let’s dive a little bit into how we can make a class immutable. There are a couple of things that we need to keep in mind while designing our classes:

  • Don’t expose internal state in an mutable way
  • Don’t change the state internally
  • Make sure subclasses don’t override the above behaviour

With the following guidelines in place, let’s design a better version of our Person class.

public final class Person {// final class, can’t be overridden by subclasses
    private final String name;     // final for safe publication in multithreaded applications
    private final List<Address> addresses;
    public Person(String name, List<Address> addresses) {
        this.name = name;
        this.addresses = List.copyOf(addresses);   // makes a copy of the list to protect from outside mutations (Java 10+).
                // Otherwise, use Collections.unmodifiableList(new ArrayList<>(addresses));
    }
    public String getName() {
        return this.name;   // String is immutable, okay to expose
    }
    public List<Address> getAddresses() {
        return addresses; // Address list is immutable
    }
}
public final class Address {    // final class, can’t be overridden by subclasses
    private final String city;   // only immutable classes
    private final String country;
    public Address(String city, String country) {
        this.city = city;
        this.country = country;
    }
    public String getCity() {
        return city;
    }
    public String getCountry() {
        return country;
    }
}

Now, the following code can be used like this:

import java.util.List;
final Person person = new Person("John", List.of(new Address(“Sydney”, "Australia"));

Now, the above code is immutable, but due to the design of the Person and Address class, while also having a final reference, it makes it impossible to reassign the person variable to anything else.

Update: As some people mentioned, the above code was still mutable because I didn’t make a copy of the list of Addresses in the constructor. So, without calling the new ArrayList() in the constructor, it’s still possible to do the following:

final List<Address> addresses = new ArrayList<>();
addresses.add(new Address("Sydney", "Australia"));
final Person person = new Person("John", addressList);
addresses.clear();

However, since a new a copy is made in the constructor, the above code will no longer affect the copied address list reference in the Person class, making the code safe. Thanks all for spotting!

I hope the above helps in understanding the differences between final and immutability. If you have any comments or feedback, please let me know in the comments below.

Top Three Strategies for Moving From a Monolith to Microservices

One of the primary problems facing enterprises is the problem of moving from monolith to microservices. The larger the enterprise, the bigger their monolithic applications become, and it gets harder to refactor them into a microservices architecture.

Everyone seems to agree on the benefits of microservices. We covered this topic at some length in this post. However, not many seem to agree on how to undertake the migration journey. Too often, the decision-making process turns into a chicken-and-egg problem. The bigger the monolith, the bigger the stakeholders’ and management’s footprint becomes. Too much management often leads to decision paralysis and, ultimately, the journey ends up as a mess.

However, many organizations have successfully managed to make this transition. Often, it is a mix of good leadership and a well-defined strategy that determines success or failure.

Good leadership is often not in the hands of an architect or developer undertaking this journey. However, a strategy is. So, let’s look at some strategies that can help in this journey:

Implement New Functionalities as Services

I know it is hard. But if you’ve decided to transition from a monolith to microservices, you have to follow this strategy. Think of the monolithic system as a hole in the ground. To get out of a hole, you don’t dig more. In other words, you don’t add to your problems.

Often, organizations miss this part completely. They think about a grand migration strategy that will take years. However, business requirements come fast. Due to the lack of budget or time, teams end up implementing those requirements into the monolithic application. The grand migration strategy never starts for whatever reason. And, each addition to the monolith makes the goal-post move further ahead.

In order to get around this, stop increasing the size of the monolith. Don’t implement new features in the monolithic code base. Every new feature or functionality should be implemented as services. This, in turn, reduces the growth rate of the monolithic application. In other words, new features implemented as services create inertia towards the migration. It also helps demonstrate the value of the approach and ensures continuous investment.

Separate Presentation Layer From the Backend

This is an extremely powerful strategy to migrate from a monolith to microservices. A typical enterprise application usually has three layers:

  • Presentation logic that consists of modules implementing the web UI. This tier of the system is responsible for handling HTTP requests and generating HTML pages. In any respectable application, this tier has a substantial amount of code.
  • Business logic that consists of modules handling the business rules. Often, this can be quite complex in an enterprise application.
  • Data access logic that consists of modules handling the persistence of data. In other words, it deals with databases.

Usually, there is a clean separation between presentation logic and business logic. The business tier exposes a set of coarse-grained APIs. Basically, these APIs form an API Layer. In other words, this layer acts as a natural border based on which you can split the monolith. This approach is also known as horizontal slicing.

If done successfully, you’ll end up with smaller applications. One application will handle the presentation. The other application will handle the business and data access logic. There are various data management patterns for microservices that can be explored.

There are advantages to this approach:

  • You can develop, deploy, and scale both applications independently. In other words, UI developers can rapidly introduce changes to the interface. They don’t have to worry about the impact on the backend.
  • You will also have a set of well-defined APIs. Also, these APIs will be remotely accessible for use in other microservices.

Extract Business Functionalities Into Services

This is the pinnacle of moving to a microservices architecture. The previous two strategies will take you only so far. Even if you successfully implement them, you’ll still have a very monolithic code base. Basically, they can act only as a spring-board to the real deal.

If you want to make a significant move towards microservices, you need to break apart the monolithic code base. The best way to do this is by breaking up the monolith based on business functionality. Each business functionality is handled by one microservice. Each of these microservices should be independently deployable and scalable. Communication between these services should be implemented using remote API calls or through message brokers.

By using this strategy, over time, the number of business functions implemented as services will grow and your monolith will gradually shrink. This approach is also known as vertical slicing. Basically, you are dividing your domain into vertical slices or functionalities.

Conclusion

Moving from a monolith to microservices is not easy. It requires significant investment and management buy-in. On top of all that, it requires incredible discipline and skill from the team actually developing it. However, the advantages are many.

Often, it is a good idea to start small on this journey. Rather than waiting for a big one-shot move, try to take incremental steps, learn from mistakes, iterate, and try again. Also, don’t try to go for a perfect design from the get-go. Instead, be willing to iterate and improve.

Lastly, remember that microservices is not a destination but a journey. A journey of continuous improvement.

Let me know your thoughts and experiences about this in the comments section below.

How Are Your Microservices Talking

In this piece, which originally appeared here, we’ll look at the challenges of refactoring SOAs to MSAs, in light of different communication types between microservices, and see how pub-sub message transmission — as a managed Apache Kafka Service — can mitigate or even eliminate these challenges.

If you’ve developed or updated any kind of cloud-based application in the last few years, chances are you’ve done so using a Microservices Architecture (MSA), rather than the slightly more dated Service-Oriented Architecture (SOA). So, what’s the difference?

As Jeff Myerson wrote:

“If Uber were built with an SOA, their services might be:GetPaymentsAndDriverInformationAndMappingDataAPIAuthenticateUsersAndDriversAPI

“Whereas, if Uber were built instead with microservices, their APIs might be more like:

SubmitPaymentsService
GetDriverInfoService
GetMappingDataService
AuthenticateUserService
AuthenticateDriverService

“More APIs, smaller sets of responsibilities.”

With smaller sets of responsibilities for each service, it’s easier to isolate functionality. But what are microservices and how do MSAs compare to SOAs and monolithic applications?

What Are Microservices?

Simply put, microservices are a software development method where applications are structured as loosely coupled services. The services themselves are minimal atomic units which together, comprise the entire functionality of the entire app. Whereas in an SOA, a single component service may combine one or several functions, a microservice within an MSA does one thing — only one thing — and does it well.

Microservices can be thought of as minimal units of functionality, can be deployed independently, are reusable, and communicate with each other via various network protocols like HTTP (more on that in a moment).

Today, most cloud-based applications that expose a REST API are built on microservices (or may actually be one themselves). These architectures are called Microservice Architectures, or MSAs.

On the continuum from single-unit, monolithic applications to coarse-grained service-oriented architectures, MSAs offer the finest granularity, with a number of specialized, atomic services supporting the application.

Microservices vs. SOA vs. MonolithicSource: Samarpit Tuli’s Quora Answer: “What’s the difference between SOAs and Microservices?”

Some Challenges

From this, one starts to get a sense of how asynchronous communication at scale could serve as a benefit in the context of apps that pull and combine data from several APIs. Still, while most organizations are considering implementing their applications as MSAs — or already have — the task, especially when refactoring from MSAs or monoliths, is not exactly straightforward.\

For example, 37% of respondents building web apps reported that monitoring was a significant issue in one sample. Why?

Some clues can be seen in some of the challenges cited by those refactoring legacy apps to MSAs — overcoming tight coupling was cited by 28% of respondents, whereas finding where to break up monolithic components was cited by almost as many.

These types of responses suggest a few different, but actually related, conclusions:

  1. Monitoring services built on MSAs is more complicated (as opposed to SOAs or Monolithic apps) because of multiple points of failure (which exist potentially everywhere a service integrates with another).
  2. Tight coupling suggests components and protocols are inflexibly integrated point-to-point in monolithic apps or SOAs (making them difficult to maintain and build functionality around).
  3. Breaking up monolithic apps or large SOA components into atomic, independent, reusable microservices is challenging for exactly those first two reasons.

Also, what sort of problems can one expect when your application scales? We’ll look at these and suggest a solution below. But there’s one question that underlies all of the above concerns: Once we do manage to break up our apps into atomic services, what’s the best way for these services to communicate with each other?

Some Microservices Communication Patterns

In her article “Introduction to Microservices Messaging Protocols,” Sarah Roman provides an excellent breakdown of the taxonomy of communication patterns used by and between microservices:

Synchronous

Synchronous communication is when the sender of the event waits for processing and some kind of reply, and only then proceeds to other tasks. This is typically implemented as REST calls, where the sender submits an HTTP request, and then the service processes this and returns an HTTP response. Synchronous communication suggests tight coupling between services.

Asynchronous

Asynchronous communication means that a service doesn’t need to wait on another to conclude its current task. A sender doesn’t necessarily wait for a response, but either polls for results later or records a callback function or action. This typically is done over message buses like Apache Kafka and/or RabbitMQ. Asynchronous communication actually invokes loose coupling between component services, because there can be no time dependencies between sending events and a receiver acting on them.

Single Receiver

In this case, each request has one sender and one receiver. If there are multiple requests, they should be staggered, because a single receiver cannot receive and process them all at once. Again, this suggests tight coupling between sender and receiver.

Multiple Receivers

As the category indicates, there are multiple receivers processing multiple requests.

We believe that, while each of these methods (in combination) have their purpose within an MSA, the most loosely coupled arrangement of all is when microservices within a distributed application communicate with each other asynchronously, and via multiple receivers. This option implies that there are no strict dependencies between the sender, time of send, protocol, and receiver.

Pub-Sub

The pub-sub communication method is an elaboration on this latter method. The sender merely sends events — whenever there are events to be sent— and each receiver chooses, asynchronously, which events to receive.

Apache Kafka may be one of the more recent evolutions of pub-sub. Apache Kafka works by passing messages via a publish-subscribe model, where software components called producers publish (append) events in time-order to distributed logs called topics (conceptually a category-named data feed to which records are appended).

Consumers are configured to separately subscribe from these topics by offset (the record number in the topic). This latter idea — the notion that consumers simply decide what they will consume — removes the complexity of having to configure complicated routing rules into the producer or other components of the system at the beginning of the pipe.

diagram of apache kafka producers writing to and consumers reading from a topic

We argue that, when asynchronous communication to multiple receivers is required, Apache Kafka is a promising way to go, as it solves the problem of tight-coupling between components and communication, is monitorable, and facilitates breaking up larger components into atomic, granular, independent, reusable services.

Why Apache Kafka?

Routing Rules Configured by Consumer

When the routing rules are configured by the consumer (a feature of pub-sub and Apache Kafka generally), then, as mentioned, there is no need to build additional complexity into the data pipe itself. This makes it possible to decouple components from the message bus (and each other) and develop and test them independently, without worrying about dependencies.

Built-in Support for Asynchronous Messaging

All of the above makes it reasonably simple to decouple components and focus on a specific part of the application. Asynchronous messaging, when used correctly, removes yet another point of complexity by letting your services be ready for events without being synced to them.

High Throughput/Low Latency

It’s easier to have peace of mind about breaking up larger, SOA-type services into smaller, more atomic ones when you don’t have to worry about communication latency issues. Aiven managed Kafka services have been benchmarked and feature the highest throughput and lowest latency of any hosted service in the industry.

Why Managed Apache Kafka?

Apache Kafka was built to leverage the best of what came before while improving on it even more.

However, Apache Kafka can be challenging to set up. There are many options to choose from, and these vary widely depending on whether you are using an open-source, proprietary, free, or paid version (depending on the vendor). What are your future requirements?

If you were choosing a bundled solution, then your choice of version and installation type, for example, may come back to haunt you in the future, depending on the functionality and performance you later decide you need.

These challenges alone may serve as a compelling argument for a managed version. With the deployment, hardware outlay costs and effort and configuration out of your hands, you can focus entirely on the development for which you originally intended your Kafka deployment.

What’s more, managed is monitorable. Are you tracking throughput? You need not worry about where the integration points are in your app to instrument custom logging and monitoring; simply monitor each of your atomic services’ throughput via your provider’s Kafka backend and metrics infrastructure.

Auto-Scaling

What sort of problems can you expect when your application scales? Bottlenecks? Race conditions? A refactoring mess to accommodate for them?

A managed Kafka solution can scale automatically for you when the size of your data stream grows. As such, you needn’t worry when it’s time to refactor your services atomically, and you needn’t force your teams to maintain blob-style, clustered services with complicated dependencies just for the sake of avoiding latency between them.

Centralized, No-Fuss Management

If you’re managing your own cluster, you can expect to be tied down with installs, updates, managing version dependencies, and related issues. A managed solution handles all of that for you, so you can focus on your core business.

High Availability

Apache Kafka is already known for its high availability, so you never have to worry about your services being unable to communicate because a single node supporting your middleware is down.

Kafka’s ability to handle massive amounts of data and scale automatically lets you scale your data processing capabilities as your data load grows. And a managed solution has redundancy built right in.

Wrapping Up

We looked at some common challenges of refactoring from SOAs to MSAs: monitorability, tight coupling of components, and the challenges of breaking up larger monolithic or SOA components into microservices.

We considered different types of communication and looked at how a pub-sub mechanism serves asynchronous message transmission between multiple services. Finally, we examined how a managed Apache Kafka solution may be an excellent candidate for such a use case.q

Design Patterns

What is the design patterns?

Design Patterns in javaIn this design patterns tutorial, we will explain all type of design patterns in java with example. A design pattern is a common solution that is used to test generally repetitive problems in software development. The design does not exist as a complete program that can be transformed into an object or machine code but, as a template identify problems in the system and provide appropriate solutions. The design pattern testing is not present in normal procedural programming and is mostly adopted by developers in Object Oriented environment. These provide the interaction on Object-Oriented level involving classes and objects.It is used as an efficient programming approach where Object Oriented systems are being developed to provide robustly and error-free software generation.

Spring 5 Design Pattern Book

You could purchase my Spring 5 book that is with title name “Spring 5 Design Pattern“. This book is available on the Amazon and Packt publisher website. Learn various design patterns and best practices in Spring 5 and use them to solve common design problems. You could use author discount to purchase this book by using code- “AUTHDIS40“.
Spring-5-Design-Pattern

Need for Design Patterns

With the emerging needs of technology and the growth in the IT industry, typical software development practices, that required the completion of the entire software before testing, has also evolved. To avoid reverting to the stage of development after completion, a testing practice during development phase was introduced. It can be used to identify error conditions and problems in the code that may not be apparent at the time. The end modules that are obtained are already tested and are less error-prone.

Designing a template that can be reused on multiple codes saves time for test creation and is easy to understand by developers with prior experience working with it. The templates are code and problem independent and do not need to be specified by coders to deal with a problem

Types of Design Patterns

Design patterns are classified into four main categories and each individual design pattern in the category make up a total of 23 design patterns. The four main categories are:

observer-software-design-pattern-5-638

  1. Creational Pattern
  2. Structural Pattern
  3. Behavioral Pattern
  4. J2EE Pattern

Creational Patterns

Creational Pattern is mostly concerned with the manner involved with creating class instances. It is further characterized as class-creation and object-creation Patterns. The object creation or instantiation is done implicitly using design patterns rather than directly. Thus, for a use-case, there is flexibility involved with the object creation.

  • Abstract Factory
    In this pattern, a factory of related objects is created by an interface without specification of the class name. The factory passes the objects by following the Factory Pattern.
  • Builder
    This pattern is used for a stage by stage creation of a complex object by combining simple objects. The final object creation depends on the stages of the creative process but is independent of other objects.
  • Factory Method
    This pattern is employed mostly during development in Java. It provides implicit object instantiation through common interfaces.
  • Object Pool
    Object pooling is used to reduce object creation cost when it is high for certain process and thus improves performance. It employs the method of object caching and simply retrieves objects from the cache pool instead of having to create it. The number of objects in the pool can be restricted to keep from continual growth.
  • Prototype
    In Prototype patterns, object duplication is performed while performance is monitored. A prototype interface pattern is present to produce a copy of an object. It is used to restrict memory/database operations by keeping modification to a minimum using object copies.
  • Singleton
    This pattern involves the present of one class and restricting object creation to a single object. The presence of a single object removes the need for object instantiation for accessing.

Structural Patterns

Structural Patterns deal with the composition of classes and objects. Inheritance is employed for interface composition and methods for addition of new functionalities are introduced by object composition. A better understanding of the entity relationship is established. Abilities of independent interfaces are combined in structural patterns.

  • Adapter
    To link two interfaces that are not compatible and utilize their functionalities, Adapter pattern is used. It is used to provide a new interface covering for any existing class.
  • Bridge
    In Bridge Pattern, there is a structural alteration in the main and interface implementer classes without having any effect on each other. These two classes are made independent of each other and are only connected by using the bridge which is an interface.
  • Composite
    Composite Pattern is used group together objects as one object. The objects are composed in a tree structure form with the representation of individual tree nodes and the hierarchy as well. The objects belonging to the same groups are modified using this pattern.
  • Decorator
    Decorator pattern restricts the alteration of object structure while a new functionality is added to it. The initial class remains unaltered while a decorator class wraps around it and provides extra capabilities.
  • Façade
    Façade provides clients with access to the system but conceals the working of the system and its complexities. The pattern creates one class consisting of user functions and delegates provide calling facilities to the classes belonging to the systems.
  • Flyweight
    Flyweight pattern is used to reduce memory usage and improve performance by cutting on object creation. The pattern looks for similar objects that already exist to reuse it rather than creating new ones that are similar.
  • Private Class Data
    Some of the class attributes may be available without requirement and thus may be prone to be corrupted. To prevent that the attributes may be allowed to be manipulated only once during operation after which it becomes private and thus data is protected.
  • Proxy
    It is used to create objects that may represent functions of other classes or objects and the interface is used to access these functionalities.

Behavioral patterns

Behavioral pattern deals with the communication between class objects. They are used to sense the presence of already present communication patterns and may be able to manipulate these patterns.

  • Chain of responsibility
    A chain of objects is created to deal with the request so that no request goes back unfulfilled.
  • Command
    Command pattern deals with requests by hiding it inside an object as a command and sent to be to invoker object which then passes it to an appropriate object that can fulfill the request.
  • Interpreter
    Interpreter pattern is used for language or expression evaluation by creating an interface that tells the context for interpretation.
  • Iterator
    Iterator pattern is used to provide sequential access to a number elements present inside a collection object without any relevant information exchange.
  • Mediator
    Mediator pattern provides easy communication through its mediator class that allows communication for several classes.
  • Memento
    Memento pattern involves the working of three classes Memento, CareTaker, and Originator. Memento holds the restorable state of the object. Originator’s job is the creation and storing of state and CareTaker’s job is the restoration of memento states.
  • Null Object
    Null Object is used instead of specifying a Null value and is used to represent a particular operation that does nothing when created. It is basically a check for Null value without the presence of the value.
  • Observer
    A One-to-Many relationship calls for the need of Observer pattern to check the relative dependencies of objects.
  • State
    In State pattern, the behavior of a class varies with its state and is thus represented by the context object.
  • Strategy
    Strategy pattern deals with the change in class behavior at runtime. The objects consist of strategies and the context object judges the behavior at runtime of each strategy.
  • Template method
    It is used with components having similarity where a template of the code may be implemented to test both the components. The code can be changed with minor alterations.
  • Visitor
    A Visitor performs a set of operations on an element class and changes its behavior of execution. Thus the variance in the behavior of element class is dependent on the change in visitor class.

J2EE Patterns

J2EE stands for Java 2 Enterprise Edition currently known as Java Enterprise Edition (J EE). It consists of many APIs that provide software developers with the capabilities to write server-side code. The J2EE patterns deal with testing on the presentation tier as offered by Sun Java Center. These design patterns are specifically concerned with the following listed layers.

  • Presentation Layer
  • Business Layer
  • Integration Layer

Core J2EE Pattern Catalog

Presentation Tier

  • Intercepting Filter
    It is used to provide interception and manipulation of requests as well as response prior to and preceding the processing of the request.   readmore
  • Context Object
    Context Object is present to keep from using system information that is specific to the protocol and doesn’t coincide with its context.   readmore
  • Front Controller
    A centralized access point allows for non-duplication of the control logic needed to handle a request. Front Controller is to handle such request by acting as an initial point.   readmore
  • Application Controller
    It provides support for action reuse and code to view-management. The code is made more readable and maintainable as well as modular. Request handling is also improved and made more extensible.   readmore
  • View Helper
    It is used to provide a different view, hiding the logic present in the code. Now the logic and the view are completely independent to provide ease for developers and designers.   readmore
  • Composite View
    Small sub views can be created using the composite view. These sub views can be integrated to create a singular view.   readmore
  • Dispatcher View
    To be able to support a small amount of multitasking, dispatcher view is used. It provides handling and response generation for requests while a business processing is taking place.   readmore
  • Service to Worker
    It is used to perform handling of requests as well as processing of the business transaction and after that, the control is transferred to the View.   readmore

Business Tier

  • Business Delegate
    The business delegate pattern is one of the Java EE design patterns. It is used in order to decouple or reduce the coupling between the presentation tier and business services.   readmore
  • Service Locator
    The design pattern, service locator is an important part in software development. Looking up for a service is one of the core features of service locator. A robust abstraction layer performs this function. The design pattern uses a central registry called Service Locator.   readmore
  • Session Facade
    The session façade pattern’s core application is development of enterprise apps. You can also call it a logical extension of GoF designs. The pattern encases the interactions which are happening between the low-level components, which is Entity EJB.   readmore
  • Business Object
    Object-oriented programming makes use of the business object. It represents the parts of a business. A business object is able to represent things like event, person, business process, place, and concept. The business object can exist in certain forms like a product, an invoice, and the details of a particular part of a transaction.   readmore
  • Composite Entity
    It is one if the Java EE software-design patterns. The composite entity pattern performs modeling, managing and representing a set of interrelated persistent objects. It does not represent them as separate fine-grained entity beans. Composite entity beans are able to represent a graph of objects.   readmore
  • Transfer Object
    It is one of the Java EE design patterns. We need transfer object when we need to pass the data across various attributes in a packet to the server. Value Object is another name for transfer object. The transfer object is just a class of POJO which has a method of the getter and setter.   readmore

Integration Tier

  • Data Access Object
    The data access object in a computer software which is as an object which is responsible for providing abstract interface for communication to a specific form of database.   readmore
  • Service Activator
    The service activator design pattern is one of the Java EE patterns. It is an SI (spring integration) component. It is responsible for triggering or activating a service object or bean which is managed by the spring. A service activator searches through the message channel in order to look for messages.   readmore
  • Web Service Broker
    The web service broker uses web protocols and XML. We can use this pattern to expose and broker the services. Assume a circumstance, where multiple organizations are lined up in order to request info from a number of service providers.   readmore

Happy Design Patterns Learning with us!!!

What Does RandomAccess Mean?

RandomAccess is a marker interface, like the Serializable and Cloneable interfaces. All these marker interfaces do not define methods. Instead, they identify a class as having a particular capability. In the case of Serializable, the interface specifies that if the class is serialized using the serialization I/O classes, a NotSerializableException will not be thrown (unless the object contains some other class that cannot be serialized). Cloneable similarly indicates that the use of the Object.clone( ) method for a Cloneable class will not throw aCloneNotSupportedException.

The RandomAccess interface identifies that a particular java.util.List implementation has fast random access. (A more accurate name for the interface would have been “FastRandomAccess.”) This interface tries to define an imprecise concept: what exactly is fast? The documentation provides a simple guide: if repeated access using the List.get( ) method is faster than repeated access using the Iterator.next( ) method, then the List has fast random access. The two types of access are shown in the following code examples.

Repeated access using List.get( ):

Object o;
for (int i=0, n=list.size(  ); i < n; i++)
  o = list.get(i);

Repeated access using Iterator.next( ):

Object o;
for (Iterator itr=list.iterator(  ); itr.hasNext(  ); )
  o = itr.next(  );

A third loop combines the previous two loops to avoid the repeated Iterator.hasNext( ) test on each loop iteration:

Object o;
Iterator itr=list.iterator(  );
for (int i=0, n=list.size(  ); i < n; i++)
  o = itr.next(  );

This last loop relies on the normal situation where List objects cannot change in size while they are being iterated through without an exception of some sort occurring. So, because the loop size remains the same, you can simply count the accessed elements without testing at each iteration whether the end of the list has been reached. This last loop is generally faster than the previous loop with the Iterator.hasNext( ) test. In the context of the RandomAccess interface, the first loop using List.get( ) should be faster than both the other loops that use Iterator.next( ) for a list to implement RandomAccess.

How Is RandomAccess Used?

So now that we know what RandomAccess means, how do we use it? There are two aspects to using the other marker interfaces, Serializable and Cloneable: defining classes that implement them and using their capabilities via ObjectInput /ObjectOutput and Object.clone( ), respectively.RandomAccess is a little different. Of course, we still need to decide whether any particular class implements it, but the possible classes are severely restricted: RandomAccess should be implemented only in java.util.List classes. And most such classes are created outside of projects. The SDK provides the most frequently used implementations, and subclasses of the SDK classes do not need to implement RandomAccess because they automatically inherit the capability where appropriate.

The second aspect, using the RandomAccess capability, is also different. Whether a class is Serializable or Cloneable is automatically detected when you use ObjectInput/ObjectOutput and Object.clone( ). But RandomAccess has no such automatic support. Instead, you need to explicitly check whether a class implements RandomAccess using the instanceof operator:

if (listObject instanceof RandomAccess)
  ...

You must then explicitly choose the appropriate access method, List.get( ) or Iterator.next( ). Clearly, if we test for RandomAccess on every loop iteration, we would be making a lot of redundant calls and probably losing the benefit of RandomAccess as well. So the pattern to follow in usingRandomAccess makes the test outside the loop. The canonical pattern looks like this:

Object o;
if (listObject instanceof RandomAccess)
{
  for (int i=0, n=list.size(  ); i < n; i++)
  {
    o = list.get(i);
    //do something with object o
  }
   
}
else
{
  Iterator itr = list.iterator(  );
  for (int i=0, n=list.size(  ); i < n; i++)
  {
    o = itr.next(  );
    //do something with object o
   
  }
}

Speedup from RandomAccess

I tested the four code loops shown in this section, using the 1.4 release, separately testing the -client (default) and -server options. To test the effect of the RandomAccess interface, I used the java.util.ArrayList and java.util.LinkedList classes. ArrayList implements RandomAccess, while LinkedList does not. ArrayList has an underlying implementation consisting of an array with constant access time for any element, so using the ArrayList iterator is equivalent to using the ArrayList.get( ) method but with some additional overhead. LinkedList has an underlying implementation consisting of linked node objects with access time proportional to the shortest distance of the element from either end of the list, whereas iterating sequentially through the list can shortcut the access time by traversing one node after another.

Times shown are the average of three runs, and all times have been normalized to the first table cell, i.e., the time taken by the ArrayList to iterate the list using the List.get( ) method in client mode.

Loop type (loop test) and access method

ArrayList java -client

LinkedList java -client

ArrayList java -server

LinkedList java -server

loop counter (i<n) and List.get( )

100%

too long

77.5%

too long

iterator (Iterator.hasNext( )) and Iterator.next( )

141%

219%

109%

213%

iterator (i<n) and Iterator.next( )

121%

205%

98%

193%

RandomAccess test with loop from row 1 or 3

100%

205%

77.5%

193%

The most important results are in the last two rows. The last line shows the times obtained by making full use of the RandomAccess interface, and the line before that shows the most optimal general technique for iterating lists if RandomAccess is not available. The size of the lists I used for the test (and consequently the number of loop iterations required to access every element) was sufficiently large that the instanceof test had no measurable cost in comparison to the time taken to run the loop. Consequently, we can see that there was no cost (but also no benefit) in adding the instanceofRandomAccess test when iterating the LinkedList, whereas the ArrayList was iterated more than 20% quicker when the instanceof test was included.

Forward and Backward Compatibility

Can you use RandomAccess and maintain backward compatibility with VM versions prior to 1.4? There are three aspects to using RandomAccess:

  • You may want to include code referencing RandomAccess without moving to 1.4.

  • Many projects need their code to be able to run in any VM, so the code needs to be backward-compatible to run in VMs using releases earlier than 1.4, where RandomAccess does not exist.

  • You will want to make your code forward-compatible so that it automatically takes advantage of RandomAccess when running in a 1.4+ JVM.

Making RandomAccess available to your development environment is the first issue, and if you are using an environment prior to 1.4, this can be as simple as adding the RandomAccess interface to your classpath. Any version of the SDK can create the RandomAccess interface. The definition for RandomAccess is:

package java.util;
public interface RandomAccess {  }

We also need to handle RandomAccess in the runtime environment. For pre-1.4 environments, the test:

if (listObject instanceof RandomAccess)

generates a NoClassDefFoundError at runtime when the JVM tries to load the RandomAccess class (for the instanceof test to be evaluated, the class has to be loaded). However, we can guard the test so that it is executed only if RandomAccess is available. The simplest way to do this is to check whether RandomAccess exists, setting a boolean guard as the outcome of that test:

static boolean RandomAccessExists;
...
   
  //execute this as early as possible after the application starts
  try
  {
    Class c =  Class.forName("java.util.RandomAccess");
    RandomAccessExists = true;
  }
  catch (ClassNotFoundException e)
  {
    RandomAccessExists = false;
  }

Finally, we need to change our instanceof tests to use the RandomAccessExists variable as a guard:

if (RandomAccessExists && (listObject instanceof RandomAccess) )

With the guarded instanceof test, the code automatically reverts to the Iterator loop if RandomAccess does not exist and should avoid throwing a NoClassDefFoundError in pre-1.4 JVMs. And, of course, the guarded instanceof test also automatically uses the faster loop branch whenRandomAccess does exist and the list object implements it.

Singleton Design Pattern

Singleton is a part of Gang of Four design pattern and it is categorized under creational design patterns. In this article, we are going to take a deeper look into the usage of the Singleton pattern. It is one of the most simple design pattern in terms of the modelling but on the other hand this is one of the most controversial pattern in terms of complexity of usage.

Singleton pattern is a design pattern which restricts a class to instantiate its multiple objects. It is nothing but a way of defining a class. Class is defined in such a way that only one instance of class is created in the complete execution of program or project. It is used where only a single instance of class is required to control the action throughout the execution. A singleton class shouldn’t have multiple instances in any case and at any cost. Singleton classes are used for logging, driver objects, caching and thread pool, database connections.

create-singleon-class

Implementation of Singleton class

An implementation of singleton class should have following properties:

  1. It should have only one instance : This is done by providing instance of class from within the class. Outer classes or subclasses should be prevented to create the instance. This is done by making the constructor private in java so that no class can access the constructor and hence cannot instantiate it.
  2. Instance should be globally accessible : Instance of singleton class should be globally accessible so that each class can use it. In java it is done by making the access-specifier of instance public.
//A singleton class should have public visiblity
//so that complete application can use
public class GFG {
  
  //static instance of class globally accessible
  public static GFG instance = new GFG();
  private GFG() {
    // private constructor so that class
    //cannot be instantiated from outside
    //this class
  }
}

Detailed Article: Implementation of Singleton Design Pattern in Java

Initialization Types of Singleton

    Singleton class can be instantiated by two methods:

  1. Early initialization : In this method, class is initialized whether it is to be used or not. Main advantage of this method is its simplicity. You initiate the class at the time of class loading. Its drawback is that class is always initialized whether it is being used or not.
  2. Lazy initialization : In this method, class in initialized only when it is required. It can save you from instantiating the class when you don’t need it. Generally lazy initialization is used when we create a singleton class.

Examples of Singleton class

  1. java.lang.Runtime : Java provides a class Runtime in its lang package which is singleton in nature. Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime() method.
    An application cannot instantiate this class so multiple objects can’t be created for this class. Hence Runtime is a singleton class.
  2. java.awt.Desktop : The Desktop class allows a Java application to launch associated applications registered on the native desktop to handle a URI or a file.
    Supported operations include:

    • launching the user-default browser to show a specified URI;
      launching the user-default mail client with an optional mailto URI;
    • launching a registered application to open, edit or print a specified file.
    • This class provides methods corresponding to these operations. The methods look for the associated application registered on the current platform, and launch it to handle a URI or file. If there is no associated application or the associated application fails to be launched, an exception is thrown.
    • Each operation is an action type represented by the Desktop.Action class.

    This class also cannot be instantiated from application. Hence it is also a singleton class.

Applications of Singleton classes

There is a lot of applications of singleton pattern like cache-memory, database connection, drivers, logging. Some major of them are :-

  1. Hardware interface access: The use of singleton depends on the requirements. Singleton classes are also used to prevent concurrent access of class. Practically singleton can be used in case external hardware resource usage limitation required e.g. Hardware printers where the print spooler can be made a singleton to avoid multiple concurrent accesses and creating deadlock.
  2. Logger : Singleton classes are used in log file generations. Log files are created by logger class object. Suppose an application where the logging utility has to produce one log file based on the messages received from the users. If there is multiple client application using this logging utility class they might create multiple instances of this class and it can potentially cause issues during concurrent access to the same logger file. We can use the logger utility class as a singleton and provide a global point of reference, so that each user can use this utility and no 2 users access it at same time.
  3. Configuration File: This is another potential candidate for Singleton pattern because this has a performance benefit as it prevents multiple users to repeatedly access and read the configuration file or properties file. It creates a single instance of the configuration file which can be accessed by multiple calls concurrently as it will provide static config data loaded into in-memory objects. The application only reads from the configuration file at the first time and there after from second call onwards the client applications read the data from in-memory objects.
  4. Cache: We can use the cache as a singleton object as it can have a global point of reference and for all future calls to the cache object the client application will use the in-memory object.

Important points

  • Singleton classes can have only one instance and that instance should be globally accessible.
  • java.lang.Runtime and java.awt.Desktop are 2 singleton classes provided by JVM.
  • Singleton Design pattern is a type of creational design pattern.
  • Outer classes should be prevented to create instance of singleton class.

How to prevent Singleton Pattern from Reflection, Serialization and Cloning?

In this article, we will see that what are various concepts which can break singleton property of a class and how to avoid them. There are mainly 3 concepts which can break singleton property of a class. Let’s discuss them one by one.

  1. Reflection: Reflection can be caused to destroy singleton property of singleton class, as shown in following example:
    // Java code to explain effect of Reflection
    // on Singleton property
    import java.lang.reflect.Constructor;
    // Singleton class
    class Singleton
    {
        // public instance initialized when loading the class
        public static Singleton instance = new Singleton();
        
        private Singleton()
        {
            // private constructor
        }
    }
    public class GFG
    {
        public static void main(String[] args)
        {
            Singleton instance1 = Singleton.instance;
            Singleton instance2 = null;
            try
            {
                Constructor[] constructors =
                        Singleton.class.getDeclaredConstructors();
                for (Constructor constructor : constructors)
                {
                    // Below code will destroy the singleton pattern
                    constructor.setAccessible(true);
                    instance2 = (Singleton) constructor.newInstance();
                    break;
                }
            }
        
            catch (Exception e)
            {
                e.printStackTrace();
            }
            
        System.out.println("instance1.hashCode():- "
                                          + instance1.hashCode());
        System.out.println("instance2.hashCode():- "
                                          + instance2.hashCode());
        }
    }
    Output:-
    instance1.hashCode():- 366712642
    instance2.hashCode():- 1829164700
    

    After running this class, you will see that hashCodes are different that means, 2 objects of same class are created and singleton pattern has been destroyed.

    Overcome reflection issue: To overcome issue raised by reflection, enums are used because java ensures internally that enum value is instantiated only once. Since java Enums are globally accessible, they can be used for singletons. Its only drawback is that it is not flexible i.e it does not allow lazy initialization.

    //Java program for Enum type singleton
    public enum GFG
    {
      INSTANCE;
    }

    As enums don’t have any constructor so it is not possible for Reflection to utilize it. Enums have their by-default constructor, we can’t invoke them by ourself. JVM handles the creation and invocation of enum constructors internally. As enums don’t give their constructor definition to the program, it is not possible for us to access them by Reflection also. Hence, reflection can’t break singleton property in case of enums.

  2. Serialization:- Serialization can also cause breakage of singleton property of singleton classes. Serialization is used to convert an object of byte stream and save in a file or send over a network. Suppose you serialize an object of a singleton class. Then if you de-serialize that object it will create a new instance and hence break the singleton pattern.
    // Java code to explain effect of
    // Serilization on singleton classes
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutput;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    class Singleton implements Serializable
    {
        // public instance initialized when loading the class
        public static Singleton instance = new Singleton();
        
        private Singleton()
        {
            // private constructor
        }
    }
    public class GFG
    {
        public static void main(String[] args)
        {
            try
            {
                Singleton instance1 = Singleton.instance;
                ObjectOutput out
                    = new ObjectOutputStream(new FileOutputStream("file.text"));
                out.writeObject(instance1);
                out.close();
        
                // deserailize from file to object
                ObjectInput in
                    = new ObjectInputStream(new FileInputStream("file.text"));
                
                Singleton instance2 = (Singleton) in.readObject();
                in.close();
        
                System.out.println("instance1 hashCode:- "
                                                     + instance1.hashCode());
                System.out.println("instance2 hashCode:- "
                                                     + instance2.hashCode());
            }
            
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    Output:- 
    instance1 hashCode:- 1550089733
    instance2 hashCode:- 865113938
    

    As you can see, hashCode of both instances is different, hence there are 2 objects of a singleton class. Thus, the class is no more singleton.

    Overcome serialization issue:- To overcome this issue, we have to implement method readResolve() method.

    // Java code to remove the effect of
    // Serialization on singleton classes
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutput;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    class Singleton implements Serializable
    {
        // public instance initialized when loading the class
        public static Singleton instance = new Singleton();
        
        private Singleton()
        {
            // private constructor
        }
        
        // implement readResolve method
        protected Object readResolve()
        {
            return instance;
        }
    }
    public class GFG
    {
        public static void main(String[] args)
        {
            try
            {
                Singleton instance1 = Singleton.instance;
                ObjectOutput out
                    = new ObjectOutputStream(new FileOutputStream("file.text"));
                out.writeObject(instance1);
                out.close();
            
                // deserailize from file to object
                ObjectInput in
                    = new ObjectInputStream(new FileInputStream("file.text"));
                Singleton instance2 = (Singleton) in.readObject();
                in.close();
            
                System.out.println("instance1 hashCode:- "
                                               + instance1.hashCode());
                System.out.println("instance2 hashCode:- "
                                               + instance2.hashCode());
            }
            
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    Output:- 
    instance1 hashCode:- 1550089733
    instance2 hashCode:- 1550089733
    

    Above both hashcodes are same hence no other instance is created.

  3. Cloning: Cloning is a concept to create duplicate objects. Using clone we can create copy of object. Suppose, we ceate clone of a singleton object, then it wil create a copy that is there are two instances of a singleton class, hence the class is no more singleton.
    // JAVA code to explain cloning
    // issue with singleton
    class SuperClass implements Cloneable
    {
      int i = 10;
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        return super.clone();
      }
    }
    // Singleton class
    class Singleton extends SuperClass
    {
      // public instance initialized when loading the class
      public static Singleton instance = new Singleton();
      private Singleton()
      {
        // private constructor
      }
    }
    public class GFG
    {
      public static void main(String[] args) throws CloneNotSupportedException
      {
        Singleton instance1 = Singleton.instance;
        Singleton instance2 = (Singleton) instance1.clone();
        System.out.println("instance1 hashCode:- "
                               + instance1.hashCode());
        System.out.println("instance2 hashCode:- "
                               + instance2.hashCode());
      }
    }
    Output :- 
    instance1 hashCode:- 366712642
    instance2 hashCode:- 1829164700
    

    Two different hashCode means there are 2 different objects of singleton class.

    Overcome Cloning issue:- To overcome this issue, override clone() method and throw an exception from clone method that is CloneNotSupportedException. Now whenever user will try to create clone of singleton object, it will throw exception and hence our class remains singleton.

    // JAVA code to explain overcome
    // cloning issue with singleton
    class SuperClass implements Cloneable
    {
      int i = 10;
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        return super.clone();
      }
    }
    // Singleton class
    class Singleton extends SuperClass
    {
      // public instance initialized when loading the class
      public static Singleton instance = new Singleton();
      private Singleton()
      {
        // private constructor
      }
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        throw new CloneNotSupportedException();
      }
    }
    public class GFG
    {
      public static void main(String[] args) throws CloneNotSupportedException
      {
        Singleton instance1 = Singleton.instance;
        Singleton instance2 = (Singleton) instance1.clone();
        System.out.println("instance1 hashCode:- "
                             + instance1.hashCode());
        System.out.println("instance2 hashCode:- "
                             + instance2.hashCode());
      }
    }
    Output:-
    Exception in thread "main" java.lang.CloneNotSupportedException
    	at GFG.Singleton.clone(GFG.java:29)
    	at GFG.GFG.main(GFG.java:38)
    

    Now we have stopped user to create clone of singleton class. If you don;t want to throw exception you can also return the same instance from clone method.

    // JAVA code to explain overcome
    // cloning issue with singleton
    class SuperClass implements Cloneable
    {
      int i = 10;
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        return super.clone();
      }
    }
    // Singleton class
    class Singleton extends SuperClass
    {
      // public instance initialized when loading the class
      public static Singleton instance = new Singleton();
      private Singleton()
      {
        // private constructor
      }
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        return instance;
      }
    }
    public class GFG
    {
      public static void main(String[] args) throws CloneNotSupportedException
      {
        Singleton instance1 = Singleton.instance;
        Singleton instance2 = (Singleton) instance1.clone();
        System.out.println("instance1 hashCode:- "
                               + instance1.hashCode());
        System.out.println("instance2 hashCode:- "
                               + instance2.hashCode());
      }
    }
    Output:-
    instance1 hashCode:- 366712642
    instance2 hashCode:- 366712642
    

    Now, as hashcode of both the instances is same that means they represent a single instance.