Host your maven artifacts on the cloud using CloudStorageMaven

One of the major issues when dealing with large codebases in our teams has to do with artifact sharing and artifact storage.

There are various options out there that provide many features such as jfrog, nexus, archiva etc.

I have been into using them, setting them up and configuring and they certainly provide you with many features. Also having you own repository installation gives you a lot of flexibility. Furthermore docker has made things a lot easier and thus setting them up takes almost no time.

Now if you use a cloud provider like amazon, azure etc there is a more lightweight option and pretty easy to setup. By using a cloud provider such as amazon, azure or google you have cheap and easy access to storage. The storage options that they provide can also be used in order to host your private artifacts or even your public ones.

To do so you need to use a maven wagon which is capable to communicate with the storage options that your cloud provider has and this is exactly what the CloudStorageMaven project deals with.

The CloudStorageMaven project provides you with wagons interacting with Amazon S3, Azure Blob Storage and Google Cloud Storage.

If you already use one of these cloud services hosting your artificats on them seems like a no brainer and theese wagons make it a lot easier to do so.

I have compiled some tutorials on how to get started with each one of them

Happy coding!

Host your maven artifacts using Google Cloud Storage

If you use Google Cloud and you use Java for your projects then Google Cloud Storage is a great place to host your teams artifacts.

It is easy to setup and pretty cheap. Also it is much simpler than setting one of the existing repository options (jfrog, nexus, archiva etc) if you are not particularly interested in their features.

To get started you need to specify a maven wagon which supports google cloud storage.
We will use the Google storage wagon.

Let’s get started by creating a maven project

mvn archetype:generate -DgroupId=com.test.apps -DartifactId=GoogleWagonTest -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

We are going to add a simple service.

package com.test.apps;

public class HelloService {

    public String sayHello() {

        return "Hello";
    }
}

Then we are going to add the maven wagon which will upload and fetch our binaries to the google cloud storage.

    <build>
        <extensions>
            <extension>
                <groupId>com.gkatzioura.maven.cloud</groupId>
                <artifactId>google-storage-wagon</artifactId>
                <version>1.0</version>
            </extension>
        </extensions>
    </build>

Then we shall create the google cloud storage bucket which will host our artifacts.

Our bucket shall be called mavenrepository

Now that we have set up our bucket in google we shall set the distribution management on our maven project.

    <distributionManagement>
        <snapshotRepository>
            <id>my-repo-bucket-snapshot</id>
            <url>gs://mavenrepository/snapshot</url>
        </snapshotRepository>
        <repository>
            <id>my-repo-bucket-release</id>
            <url>gs://mavenrepository/release</url>
        </repository>
    </distributionManagement>

From the maven documentation

Where as the repositories element specifies in the POM the location and manner in which Maven may download remote artifacts for use by the current project, distributionManagement specifies where (and how) this project will get to a remote repository when it is deployed. The repository elements will be used for snapshot distribution if the snapshotRepository is not defined.

The next step is the most crucial and this has to to do with authenticating to google cloud.

You need to have the gcloud command line setup in your system and you must issue a login
‘gcloud auth login –brief’ with an account that has access to the bucket we created previously.
The other way is to use the GOOGLE_APPLICATION_CREDENTIALS environmental variable. You can use this GOOGLE_APPLICATION_CREDENTIALS in order to set the path to your google application credentials file.
The credentials file should also be able to access the bucket we created previously.

And now the easiest part which is deploying.

mvn deploy

Now since your artifact has been deployed you can use it in another repo by specifying your repository and your wagon.

    <repositories>
        <repository>
            <id>my-repo-bucket-snapshot</id>
            <url>gs://mavenrepository/snapshot</url>
        </repository>
        <repository>
            <id>my-repo-bucket-release</id>
            <url>gs://mavenrepository/release</url>
        </repository>
    </repositories>

    <build>
        <extensions>
            <extension>
                <groupId>com.gkatzioura.maven.cloud</groupId>
                <artifactId>google-storage-wagon</artifactId>
                <version>1.0</version>
            </extension>
        </extensions>
    </build>

That’s it! Next thing you know, your artifact will be downloaded by maven through google cloud storage and used as a dependency in your new project.

Host your maven artifacts using Amazon s3

If you use amazon Web Services and you use Java for your projects then Amazon S3 is a great place to host your teams artifcats.

It is easy to setup and pretty cheap. Also it is much simpler than setting one of the existing repository options (jfrog, nexus, archiva etc) if you are not particularly interested in their features.

To get started you need to specify a maven wagon which supports s3.
We will use the s3 storage wagon.

Let’s get started by creating a maven project

mvn archetype:generate -DgroupId=com.test.apps -DartifactId=S3WaggonTest -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

We are going to add a simple service.

package com.test.apps;

public class HelloService {

    public String sayHello() {

        return "Hello";
    }
}

Then we are going to add the maven wagon which will upload and fetch our binaries to s3.

    <build>
        <extensions>
            <extension>
                <groupId>com.gkatzioura.maven.cloud</groupId>
                <artifactId>s3-storage-wagon</artifactId>
                <version>1.0</version>
            </extension>
        </extensions>
    </build>

Then we shall create the s3 bucket that will host our artifacts.

aws s3 createbucket artifactbucket.

Now we have create our bucket. Then we shall set the distribution management on our maven project.

    <distributionManagement>
        <snapshotRepository>
            <id>my-repo-bucket-snapshot</id>
            <url>s3://my-test-repo/snapshot</url>
        </snapshotRepository>
        <repository>
            <id>my-repo-bucket-release</id>
            <url>s3://my-test-repo/release</url>
        </repository>
    </distributionManagement>

From the maven documentation

Where as the repositories element specifies in the POM the location and manner in which Maven may download remote artifacts for use by the current project, distributionManagement specifies where (and how) this project will get to a remote repository when it is deployed. The repository elements will be used for snapshot distribution if the snapshotRepository is not defined.

The next step is the most crucial and this has to to do with authenticating to aws.
There easy way is to have aws cli configured to point to the region where your bucket is located and with credentials which have read and write access to the s3 bucket which will host your binaries.

aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-west-2
Default output format [None]: json

The other way is to use the maven way and specify our aws credentials on the ~/.m2/settings.xml

  <servers>
    <server>
      <id>my-repo-bucket-snapshot</id>
      <username>EXAMPLEEXAMPLEXAMPLE</username>
      <password>eXampLEkeyEMI/K7EXAMP/bPxRfiCYEXAMPLEKEY</password>
    </server>
    <server>
      <id>my-repo-bucket-release</id>
      <username>EXAMPLEEXAMPLEXAMPLE</username>
      <password>eXampLEkeyEMI/K7EXAMP/bPxRfiCYEXAMPLEKEY</password>
    </server>
  </servers>

Be aware that you have to specify credentials for each repository specified.
Also we are not over yer since It is crucial to specify the region of the bucket.
To do so you you can either set it up the Amazon way therefore specifying it in an environmental variable

AWS_DEFAULT_REGION=us-east-1

Or you can pass it as a property while executing the deploy command.

-DAWS_DEFAULT_REGION=us-east-1

And now the easiest part which is deploying.

mvn deploy

Now since your artifact has been deployed you can use it in another repo by specifying your repository and your wagon.

    <repositories>
        <repository>
            <id>my-repo-bucket-snapshot</id>
            <url>s3://my-test-repo/snapshot</url>
        </repository>
        <repository>
            <id>my-repo-bucket-release</id>
            <url>s3://my-test-repo/release</url>
        </repository>
    </repositories>

    <build>
        <extensions>
            <extension>
                <groupId>com.gkatzioura.maven.cloud</groupId>
                <artifactId>s3-storage-wagon</artifactId>
                <version>1.0</version>
            </extension>
        </extensions>
    </build>

That’s it! Next thing you know your artifact will be downloaded by maven through s3 and used as a dependency in your new project.

Host your maven artifacts using Azure Blob Storage

If you use Microsoft Azure and you use Java for your projects then Azure Blob Storage is a great place to host your teams artifcats.

It is easy to setup and pretty cheap. Also it is much simpler than setting one of the existing repository options (jfrog, nexus, archiva etc) if you are not particularly interested in their features.

To get started you need to specify a maven wagon which supports azure blob storage.
We will use the Azure storage wagon.

Let’s get started by creating a maven project

mvn archetype:generate -DgroupId=com.test.apps -DartifactId=AzureWagonTest -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

We are going to add a simple service.

package com.test.apps;

public class HelloService {

    public String sayHello() {

        return "Hello";
    }
}

Then we are going to add the maven wagon which will upload and fetch our binaries to azure blob storage.

    <build>
        <extensions>
            <extension>
                <groupId>com.gkatzioura.maven.cloud</groupId>
                <artifactId>azure-storage-wagon</artifactId>
                <version>1.0</version>
            </extension>
        </extensions>
    </build>

Then we shall create the azure storage account that will host our artifacts.

Then we shall create a new container called snapshot. This container will contain our snapshot repositories.

We can go through the same process in order to create a release repository.
Be aware that there is no need to to create different containers for each repository. You can have repositories under the same container.

Now that we have set up our storage account in azure we shall set the distribution management on our maven project.

    <distributionManagement>
        <snapshotRepository>
            <id>my-repo-bucket-snapshot</id>
            <url>bs://mavenrepository/snapshot</url>
        </snapshotRepository>
        <repository>
            <id>my-repo-bucket-release</id>
            <url>bs://mavenrepository/release</url>
        </repository>
    </distributionManagement>

From the maven documentation

Where as the repositories element specifies in the POM the location and manner in which Maven may download remote artifacts for use by the current project, distributionManagement specifies where (and how) this project will get to a remote repository when it is deployed. The repository elements will be used for snapshot distribution if the snapshotRepository is not defined.

The next step is the most crucial and this has to to do with authenticating to azure.

What you need is your storage account name and the key of the storage account.
In order to retrieve both you have to navigate to the Access keys of your Storage Account at the Settings section.

Then we shall specify our storage account credentials on the ~/.m2/settings.xml

  <servers>
    <server>
      <id>my-repo-bucket-snapshot</id>
      <username>mavenrepository</username>
      <password>eXampLEkeyEMI/K7EXAMP/bPxRfiCYEXAMPLEKEY</password>
    </server>
    <server>
      <id>my-repo-bucket-release</id>
      <username>mavenrepository</username>
      <password>eXampLEkeyEMI/K7EXAMP/bPxRfiCYEXAMPLEKEY</password>
    </server>
  </servers>

Be aware that you have to specify credentials for each repository specified.

And now the easiest part which is deploying.

mvn deploy

Now since your artifact has been deployed you can use it in another repo by specifying your repository and your wagon.

    <repositories>
        <repository>
            <id>my-repo-bucket-snapshot</id>
            <url>bs://mavenrepository/snapshot</url>
        </repository>
        <repository>
            <id>my-repo-bucket-release</id>
            <url>bs://mavenrepository/release</url>
        </repository>
    </repositories>

    <build>
        <extensions>
            <extension>
                <groupId>com.gkatzioura.maven.cloud</groupId>
                <artifactId>azure-storage-wagon</artifactId>
                <version>1.0</version>
            </extension>
        </extensions>
    </build>

That’s it! Next thing you know your artifact will be downloaded by maven through azure blob storage and used as a dependency in your new project.

Creational Design Patterns: Prototype Pattern

The prototype pattern is used in order to create a copy of an object. This pattern can be really useful especially when creating an object from scratch is costly.
In comparison with the builder, factory and abstract factory patterns it does not create an object from scratch it clones/recreates it.
In comparison with the singleton pattern it creates multiple copies of an instance whilst the singleton has to ensure that only one will exist.

Imagine the scenario of an object, which in order to be created requires a very resource intensive method. It can be a database query with many joins or even the result of a Federated search.
We want those data to be processed by various algorithm using one thread per algorithm. Every thread should have its own copy of the original instance, since using the same object will result to inconsistent results.

So we have an interface for representing the result of a Search.

package com.gkatzioura.design.creational.prototype;

public interface SearchResult {

    SearchResult clone();

    int totalEntries();

    String getPage(int page);
}

And we have the implementation of the SearchResult the FederatedSearchResult.

package com.gkatzioura.design.creational.prototype;

import java.util.ArrayList;
import java.util.List;

public class FederatedSearchResult implements SearchResult {

    private List<String> pages = new ArrayList<String>();

    public FederatedSearchResult(List<String> pages) {
        this.pages = pages;
    }

    @Override
    public SearchResult clone() {

        final List<String> resultCopies = new ArrayList<String>();
        pages.forEach(p->resultCopies.add(p));
        FederatedSearchResult federatedSearchResult = new FederatedSearchResult(resultCopies);
        return federatedSearchResult;
    }

    @Override
    public int totalEntries() {
        return pages.size();
    }

    @Override
    public String getPage(int page) {
        return pages.get(page);
    }
}

So we can use the clone method and create as many copies as we need of a very expensive object to create.

You can find the sourcecode on github.

Also I have compiled a cheat sheet containing a summary of the Creational Design Patterns.
Sign up in the link to receive it.

Creational Design Patterns: Singleton Pattern

The singleton design pattern is a software design pattern the restricts the the instantiation of a class to one object.
In comparison with other creational design patterns such as the abstract factory, factory and the builder pattern the singleton will create an object but will also be responsible so that only one instance of that object exists.

When creating a class as a singleton there are some certain problems that is has to tackle.

  • How can it be ensured that a class has only one instance.
  • How can the sole instance of a class be accessed easily
  • How can a class control its instantiation
  • How can the number of instances of a class be restricted

 

Suppose we have a class that sends messages.
The Messenger class.

package com.gkatzioura.design.creational.singleton;

public class Messenger {

    public void send(String message) {
        
    }
}

However we want the message procedure to be handled only by one instance of the Messenger class. Imagine the scenario where the Messenger class opens a tcp connection (for example xmpp) and has to keep the connection alive in order to send messages. It will be pretty inefficient to open a new xmpp connection each time we have to sent a message.

Therefore we will proceed and make the messenger class a singleton.

package com.gkatzioura.design.creational.singleton;

public class Messenger {

    private static Messenger messenger = new Messenger();

    private Messenger() {}

    public static Messenger getInstance() {
        return messenger;
    }

    public void send(String message) {

    }
}

As you can see we set the messenger constructor as private, and we initialized a messenger using a static variable.
Static variables are class level variables, memory allocation only happens once when the class is loaded in the memory. By this way we ensure that the messenger class will be instantiated only once.
The getInstance method will fetch the static messenger instance once called.

Obviously the previous approach has its pros and cons.
We don’t have to worry on thread safety and the instance will be created only when the Messenger class will be loaded. However it lacks in flexibility. Consider the scenario of passing configuration variables to the Messenger constructor. It is not possible using the previous approach.

A workaround is to instantiate the messenger class on the getInstance method.

package com.gkatzioura.design.creational.singleton.lait;

public class Messenger {

    private static Messenger messenger;

    private Messenger() {}

    public static Messenger getInstance() {

        if(messenger==null) {
            messenger = new Messenger();
        }

        return messenger;
    }
    
    public void send(String message) {

    }
}

The above approach might work in certain case but it misses on thread safety in cases where the class might get instantiated in a multithreaded environment.

The easiest approach to make our class thread safe is to synchronize the getInstance method.

package com.gkatzioura.design.creational.singleton.lait;

public class Messenger {

    private static Messenger messenger;

    private Messenger() {}

    public synchronized static Messenger getInstance() {

        if(messenger==null) {
            messenger = new Messenger();
        }

        return messenger;
    }

    public void send(String message) {

    }
}

That one will work. At least the creation of the messenger will be synchronized and no duplicates will be created.
The problem with this approach is that the synchronization is only needed once when the object is created. Using the above code will lead to unnecessary overhead.

The other approach is to use the Double-Checked Locking approach. Now Double-Checked locking needs extra care since it is easy to pick the broken implementation over the correct one.
The best approach is to implement lazy loading using the volatile keyword.

package com.gkatzioura.design.creational.singleton.dcl;

public class Messenger {

    private static final Object lock = new Object();
    private static volatile Messenger messenger;

    private Messenger() {}

    public static Messenger getInstance() {

        if(messenger==null) {
            synchronized (lock) {
                if(messenger==null) {
                    messenger = new Messenger();
                }
            }
        }

        return messenger;
    }

    public void send(String message) {

    }
}

By using the volatile keyword we prevent the write of a volatile to be reordered with respect to any previous read or write and a read of a volatile to be reordered with respect to any following read or write.
Also a mutex object is used to achieve synchronization.

To sum up we created an object and we also made sure that there will be only one instance of that object. Also we made sure that there won’t be any problem on instantiating the object in a multi-threaded environment.

You can find the sourcecode on github.

On the next blog post we will have a look at the prototype pattern.

Also I have compiled a cheat sheet containing a summary of the Creational Design Patterns.
Sign up in the link to receive it.

Creational Design Patterns: Builder Pattern

Previously we had a look at the factory and the abstract factory pattern. Those patterns serve their purpose and can be really useful however there are use cases where we have to create a very complex object and creating it requires different steps each one requiring different actions. In such cases the builder pattern can be really useful.
The builder design pattern is a creational design pattern and can be used in order to create complex objects step by step.

Supposing we have an object with many dependencies and in order to acquire each one these dependencies some certain actions have to be issued.
In such cases we can use the builder pattern in order to

  • Encapsulate creating and assembling the parts of a complex object in a separate Builder object.
  • Delegate the object creation to a Builder object instead of creating the objects directly.

Imagine the scenario of a backend system that has to compose and sent emails.
Creating an email might be a complex procedure. You have to specify the title, set the recipients, add a greeting add a closing statement. You might also want to use mustache instead. There is a wide range of options.

Having one class for all the actions needed to create an email might make our class bloated and loose its original purpose.

So we will start with the class responsible for sending the email.

package com.gkatzioura.design.creational.builder;

public class Email {

    private final String title;
    private final String recipients;
    private final String message;

    public Email(String title, String recipients, String message) {
        this.title = title;
        this.recipients = recipients;
        this.message = message;
    }

    public String getTitle() {
        return title;
    }

    public String getRecipients() {
        return recipients;
    }

    public String getMessage() {
        return message;
    }

    public void send() {

    }
}

As you can see the class contains only three string fields and there is no extra processing on them. So we shall create a builder class which will handle the message formatting, the recipient representation and the creation of the Email class.

package com.gkatzioura.design.creational.builder;

import java.util.HashSet;
import java.util.Set;

public class EmailBuilder {

    private Set recipients = new HashSet();
    private String title;
    private String greeting;
    private String mainText;
    private String closing;

    public EmailBuilder addRecipient(String recipient) {
        this.recipients.add(recipient);
        return this;
    }

    public EmailBuilder removeRecipient(String recipient) {
        this.recipients.remove(recipient);
        return this;
    }

    public EmailBuilder setTitle(String title) {
        this.title = title;
        return this;
    }

    public EmailBuilder setGreeting(String greeting) {
        this.greeting = greeting;
        return this;
    }

    public EmailBuilder setMainText(String mainText) {
        this.mainText = mainText;
        return this;
    }

    public EmailBuilder setClosing(String closing) {
        this.closing = closing;
        return this;
    }

    public Email create() {

        String message = greeting+"\n"+mainText+"\n"+closing;
        String recipientSection = commaSeparatedRecipients();

        return new Email(title,recipientSection,message);
    }

    private String commaSeparatedRecipients() {

        StringBuilder sb = new StringBuilder();
        for(String recipient:recipients) {
            sb.append(",").append(recipient);
        }

        return sb.toString().replaceFirst(",","");
    }

}

The next is step to make the email creation more strict so that creating an Email would only be possible through the EmailBuilder.

package com.gkatzioura.design.creational.builder;

import java.util.HashSet;
import java.util.Set;

public class Email {

    private final String title;
    private final String recipients;
    private final String message;

    private Email(String title, String recipients, String message) {
        this.title = title;
        this.recipients = recipients;
        this.message = message;
    }

    public String getTitle() {
        return title;
    }

    public String getRecipients() {
        return recipients;
    }

    public String getMessage() {
        return message;
    }

    public void send() {

    }

    public static class EmailBuilder {

        private Set recipients = new HashSet();
        private String title;
        private String greeting;
        private String mainText;
        private String closing;

        public EmailBuilder addRecipient(String recipient) {
            this.recipients.add(recipient);
            return this;
        }

        public EmailBuilder removeRecipient(String recipient) {
            this.recipients.remove(recipient);
            return this;
        }

        public EmailBuilder setTitle(String title) {
            this.title = title;
            return this;
        }

        public EmailBuilder setGreeting(String greeting) {
            this.greeting = greeting;
            return this;
        }

        public EmailBuilder setMainText(String mainText) {
            this.mainText = mainText;
            return this;
        }

        public EmailBuilder setClosing(String closing) {
            this.closing = closing;
            return this;
        }

        public Email build() {

            String message = greeting+"\n"+mainText+"\n"+closing;
            String recipientSection = commaSeparatedRecipients();

            return new Email(title,recipientSection,message);
        }

        private String commaSeparatedRecipients() {

            StringBuilder sb = new StringBuilder();
            for(String recipient:recipients) {
                sb.append(",").append(recipient);
            }

            return sb.toString().replaceFirst(",","");
        }

    }
}

The end result of using the builder pattern for creating an email will be like this.

Email email = new Email.EmailBuilder()
    .addRecipient("john@Doe.com")
    .setMainText("Check the builder pattern")
    .setGreeting("Hi John!")
    .setClosing("Regards")
    .setTitle("Builder pattern resources")
    .build();

To summarize by using the builder pattern we were able to create a complex object and its complex parts.

You can find the sourcecode on github.

On the next blog we will talk about the singleton pattern.

Also I have compiled a cheat sheet containing a summary of the Creational Design Patterns.
Sign up in the link to receive it.

Creational Design Patterns: Factory Pattern

Previously we had an introduction to the Creational Patterns and used the Abstract Factory Pattern in order to create a families of objects.

The next pattern is the Factory Pattern. Factory pattern is one of the most used patterns when it comes to Java.
So what is the Factory Pattern all about? The factory pattern deals with creating objects without specifying the exact class or the object that will be created.

Let’s get into action by using the factory pattern for a Voucher problem.
Supposing we have a loyalty feature in our application which, depending on the customer’s transactions, rewards the customer with some vouchers.
The voucher requires a voucher code and since it will be displayed on the application it requires a specially formatted html message.

The first step is to create the voucher interface.

package com.gkatzioura.design.creational.factory;

public interface Voucher {

    public String code();

    public String htmlMessage();
}

We will have two types of Vouchers for now however it will be easy to add more once the business people come with more ideas.

The first one is the food Voucher.

package com.gkatzioura.design.creational.factory;

import java.util.UUID;

public class FoodVoucher implements Voucher {

    private UUID code;
    private static final String htmlMessage= "<html><body>
<h1>Food Voucher</h1>

</body></html>";

    public FoodVoucher() {
        code = UUID.randomUUID();
    }

    public String code() {
        return code.toString();
    }

    public String htmlMessage() {
        return htmlMessage;
    }
}

And the second one it the clothes voucher.

package com.gkatzioura.design.creational.factory;

import java.util.UUID;

public class ClothesVoucher implements Voucher {

    private UUID code;
    private static final String htmlMessage = "<html><body>
<h1>Clothes Voucher</h1>

</body></html>";

    public ClothesVoucher() {
        code = UUID.randomUUID();
    }

    public String code() {
        return code.toString();
    }

    public String htmlMessage() {
        return htmlMessage;
    }
}

The vouchers will be created based on a transaction-points system.
The food voucher will be created in cases of less than 30 transaction points. For transaction-points higher than 30 the clothes voucher shall be created.
So the next step is to create the mechanism that will create the vouchers based on the transaction points.
The best candidate for this is the Factory Pattern.

package com.gkatzioura.design.creational.factory;

public class VoucherFactory {

    public Voucher create(Integer discountPoints) {

        if(discountPoints<=0) {
            throw new IllegalArgumentException("Invalid number of discount points!");
        }

        if(discountPoints<30) {
            return new FoodVoucher();
        } else {
            return new ClothesVoucher();
        }
    }

}

To sum up by choosing the factory pattern

  • We create the vouchers needed without exposing to the client any creation logic.
  • The client does not have to specify the exact class of the object that will be created.

You can find the source code on github.

On the next blog post we will have a look at the builder pattern.

Also I have compiled a cheat sheet containing a summary of the Creational Design Patterns.
Sign up in the link to receive it.

Creational Design Patterns: Abstract Factory Pattern

The Abstract Factory Pattern is a creational pattern and is one of the most popular patterns along with the builder and the factory pattern. Creational patterns are used in order to create objects instead of creating objects directly using a constructor.

The Abstract Factory Pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes.

The intent in employing the pattern is to insulate the creation of objects from their usage and to create families of related objects without having to depend on their concrete classes.

By using that pattern the client doesn’t have to be aware of the objects and their implementation details. It is a responsibility of the Abstract Factory’s Implementation to implement the objects and handle all the details in order to do that successfully.

So let’s get into action and start solving problems.
Supposing we are responsible for the canning process of various products.
Regarding the canning procedure there are two objects that have to be created. The can’s main body and the can’s top.
Also considering the fact that we might have various forms of canning we might as well have various factories which can handle the canning process. For example we might have a factory for beer canning or a factory for food canning.

Regarding the description above it seems that abstract factory is the way to go. We do have a family of objects and we do want to hide the construction of these objects.

We will start by adding two interfaces regarding the functionality of a can’s top and a can’s body.

package com.gkatzioura.design.creational.abstractfactory;

public interface CanTop {

    void open();

}
package com.gkatzioura.design.creational.abstractfactory;

public interface CanBody {

    void fill();

}

Then we shall create an abstract factory which will provide the methods to implement in order to create those objects.

package com.gkatzioura.design.creational.abstractfactory;

public abstract class CanningFactory {

    public abstract CanTop createTop();

    public abstract CanBody createBody();

}

As mentioned we have cases of beer canning. Thus we will have implementations of the CanTop and the CanBody class.

package com.gkatzioura.design.creational.abstractfactory.beer;

import com.gkatzioura.design.creational.abstractfactory.CanTop;

public class BeerCanTop implements CanTop {

    public void open() {

    }
}
package com.gkatzioura.design.creational.abstractfactory.beer;

import com.gkatzioura.design.creational.abstractfactory.CanBody;

public class BeerCanBody implements CanBody {

    public void fill() {

    }
}

Then we shall implement a Beer Canning Factory.

package com.gkatzioura.design.creational.abstractfactory.beer;

import com.gkatzioura.design.creational.abstractfactory.CanBody;
import com.gkatzioura.design.creational.abstractfactory.CanTop;
import com.gkatzioura.design.creational.abstractfactory.CanningFactory;

public class BeerCanningFactory extends CanningFactory {

    public CanTop createTop() {
        return new BeerCanTop();
    }

    public CanBody createBody() {
        return new BeerCanBody();
    }

}

The other case is food canning. We will provide implementations of the CanTop and CanBody class for this case too.

package com.gkatzioura.design.creational.abstractfactory.food;

import com.gkatzioura.design.creational.abstractfactory.CanBody;

public class FoodCanBody implements CanBody {

    public void fill() {

    }
}
package com.gkatzioura.design.creational.abstractfactory.food;

import com.gkatzioura.design.creational.abstractfactory.CanTop;

public class FoodCanTop implements CanTop {

    public void open() {

    }
}

As a last step we will provide the abstract factory implementation for cases of food canning.

package com.gkatzioura.design.creational.abstractfactory.food;

import com.gkatzioura.design.creational.abstractfactory.CanBody;
import com.gkatzioura.design.creational.abstractfactory.CanTop;
import com.gkatzioura.design.creational.abstractfactory.CanningFactory;

public class FoodCanningFactory extends CanningFactory {

    public CanTop createTop() {
        return new FoodCanTop();
    }

    public CanBody createBody() {
        return new FoodCanBody();
    }

}

What we just did is using the abstract factory pattern in order to create a family of objects regarding the canning process. We insulated the creation process from the usage of the CanTop and CanBody. Also we are able to create a family of objects without depending on their concrete classes.

You can find the sourcecode on github.

On the next blog post we will have a look at the Factory Pattern.

Also I have compiled a cheat sheet containing a summary of the Creational Design Patterns.
Sign up in the link to receive it.

Solid Principles: Dependency inversion principle

Up until now we had a look on the single responsibility, open/closed, liskov substitution and interface segregation principles.
Dependency Inversion is one of the last principle we are gone look at.
The principle states that

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.

Let’s get started with some code that violates that principle.
As a software team and we need to implement a project. For now the software team consists of:

A BackEnd Developer

package com.gkatzioura.solid.di;

public class BackEndDeveloper {

    public void writeJava() {
    }
}

And a FrontEnd developer

package com.gkatzioura.solid.di;

public class FrontEndDeveloper {

    public void writeJavascript() {
    }

}

And our project uses both throughout the development process.

package com.gkatzioura.solid.di;

public class Project {

    private BackEndDeveloper backEndDeveloper = new BackEndDeveloper();
    private FrontEndDeveloper frontEndDeveloper = new FrontEndDeveloper();

    public void implement() {

        backEndDeveloper.writeJava();
        frontEndDeveloper.writeJavascript();
    }

}

So as we can see the Project class is a high level module and it depends on low level modules such as BackEndDeveloper and FrontEndDeveloper. We are actually violating the first part of the dependency inversion principle.

Also by the inspecting the implement function of the Project.class we realise that the methods writeJava and writeJavascript are methods bound to the corresponding classes. Regarding the project scope those are details since in both cases they are forms of development. Thus the second part of the dependency inversion principle is violated.

In order to tackle this problem we shall implement and interface called the Developer interface.

package com.gkatzioura.solid.di;

public interface Developer {

    void develop();
}

Therefore we introduce an abstraction.

The BackEndDeveloper shall be refactored to

package com.gkatzioura.solid.di;

public class BackEndDeveloper implements Developer {

    @Override 
    public void develop() {
        writeJava();
    }
    
    private void writeJava() {
    }
    
}

And the FrontEndDeveloper shall be refactored to

package com.gkatzioura.solid.di;

public class FrontEndDeveloper implements Developer {

    @Override 
    public void develop() {
        writeJavascript();
    }
    
    public void writeJavascript() {
    }
    
}

The next step in order to tackle the violation of the first part would be to refactor the Project class so that it will not depend on the FrontEndDeveloper and the BackendDeveloper class.

package com.gkatzioura.solid.di;

import java.util.List;

public class Project {

    private List<Developer> developers;
    
    public Project(List<Developer> developers) {
    
        this.developers = developers;
    }

    public void implement() {

        developers.forEach(d->d.develop());
    }

}

The outcome is that the Project class does not depend on lower level modules but abstractions. Also low-level modules and their details depend on abstractions.

You can find the source code on github.

Also I have compiled a cheat sheet containing a summary of the solid principles.
Sign up in the link to receive it.