Hi everyone, I’m Pink_1

I provide a HR consultancy and coaching service to SMES, specialising in looking after you and your people, by providing a flexible range of people services, to prepare your business for survival and growth in this difficult trading climate. We have big experience but are small enough to care about you and your business. pinkphoenix

MB-920 Study Material Best Sources of Mean Offered by Realexamdumps

Do you want loads of job employment possibilities to bang on your door? Then obtain a Microsoft Certified: Dynamics 365 Fundamentals Finance and Operations Apps (ERP) accreditation an accreditation on a CV certainly snags the bosses appreciation. Microsoft Dynamics 365 Fundamentals Finance and Operations Apps (ERP) Practice Exam Questions prepare you with expertise that is desirable and latest. You are perhaps contemplating accreditation tests are like a bother. However what in case i informed you that you could obtain equal to 90% passing cut score in only some days or hours even. Come to Realexamdumps now to obtain your cheap, genuine MB-920 practice questions. There is likewise the service of money off, without charge tutorial and a refund assurance. Thus, clearing in the one-shot isnt the just plus bonus of these MB-920 Online Test Engine. Thus, stand up and obtain your resources instantly.

Composite Requests in Salesforce Are a Great Idea

Of all the development eras I’ve witnessed in my 30+ years building apps and features, the RESTful API design pattern is my favorite. Prior to the RESTful approach, I always felt like something was missing when developing web applications.

My concerns were put to rest when I attended the Gartner Enterprise Architecture Summit in 2008. Most notably, a session called “SOAP v REST” was not only informative and funny, but it opened my eyes. I walked away with a desire to understand more about RESTful APIs and soon started experimenting with this new design pattern during my personal time.

6 Best Reseller Hosting Plans of 2021 (Best Value + Quality)

Are you looking for the best reseller hosting?

Reseller hosting lets you sell hosting services just like a web hosting company. Web designers, developers, and agencies can offer reseller hosting as an addon service for clients and customers.

In this article, we’ll share our favorite reseller hosting so that you can choose the right hosting company for your business.

Best reseller hosting of 2021 (compared)

What is Reseller Hosting and Who is it For?

With reseller hosting, you purchase web hosting services and then sell the server space and features to other customers.

Think of it like running your own web hosting business, but without all of the expensive costs like hardware, servers, maintenance, support, and more. Every technical task is managed behind the scenes by the web host.

It’s important to choose a high quality hosting provider, since their service will be the foundation for your business.

If you’re a developer, agency, or manage WordPress websites for clients in any way, then reselling hosting can be a great way to make money online.

With that said, let’s take a look at some of the best reseller hosting options available on the market today.

1. SiteGround

SiteGround Reseller

SiteGround is a popular hosting provider that’s known for its high quality support and fast loading speeds. It’s also one of the hosts officially recommended by WordPress.

The reseller hosting plans let you pass on all of SiteGround’s great hosting features to your clients.

All reseller packages support an unlimited number of hosting accounts, have free WordPress installation and updates, daily backups, and more.

Free SSL certificates, email accounts, and a CDN are included with your customers’ hosting accounts too.

You can also offer your clients access to the site staging features, datacenter selection, and free migration for those coming from other web hosts.

Pricing: SiteGround reseller plans start at $7.99 and include 20GB of storage and support for unlimited websites. If you want custom branding for your account, then you’ll need one of the higher priced plans.

For more details, see our SiteGround review to learn more about the features, performance, and more.

2. HostGator

HostGator Reseller

HostGator is one of the top WordPress hosting providers in the world. They’ve been around since 2002 and have grown to become one of the biggest and most beginner friendly hosts in the market.

The reseller hosting offers great features like unlimited domains, a free SSL certificate, dedicated IP addresses, FTP accounts, private name servers, automated backups, and more.

Every reseller plan comes with the WHM control panel for easier client management and server control. You can monitor and control the server bandwidth and disk space for every customer server.

It also includes WHMCS billing software to easily automate your billing.

Finally, HostGator includes 24/7 support via live chat and phone.

Pricing: HostGator reseller plans start at $19.95 per month and have 60GB of disk space and support for unlimited websites.

To learn more about HostGator, see our in depth HostGator review where we evaluate their speed, performance, and support.

3. GreenGeeks

GreenGeeks Reseller

GreenGeeks is well known in the hosting industry for being an environmentally friendly host. They offer very fast loading speeds, 24/7 US-based support, and power over 600,000 websites.

Every reseller plan includes unlimited disk space and bandwidth, a free CDN, and automated daily backups. Plus, high level plans can support eCommerce stores across different platforms like WooCommerce.

If your clients are more advanced users, then you can offer support for multiple versions of PHP, FTP access, WP-CLI, Git, and more.

White label services are also available, so you can sell hosting under your branding instead of GreenGeeks.

Pricing: GreenGeeks reseller plans start at $19.95 per month with 60GB of disk space and support for 25 cPanel accounts.

To learn more about GreenGeeks, see our in depth GreenGeeks review where we cover the pros and cons in depth.

4. WP Engine

WP Engine Managed Hosting

WP Engine is known for its managed WordPress hosting plans, rock solid support team, and fast speeds.

It’s very popular with WordPress developers since it offers support for up to 30 websites on managed hosting when you choose the Managed Hosting Scale plan.

You get access to 24/7 support, automated migrations, daily backups, SSH access, and a free SSL certificate with managed hosting.

Plus, with WP Engine, you get access to 10 different StudioPress WordPress themes that you can use on client websites.

Pricing: WP Engine starts at $241.67 per month when billed yearly and supports up to 30 websites.

For more details, see our in depth WP Engine review where we highlight the pros, cons, performance, and more.

5. A2 Hosting

A2 Reseller Hosting

A2 Hosting is a web host known for its speed, performance, and reliability. There’s also 24/7 tech support to assist with any website issues.

All of the reseller hosting plans are managed with the Web Host Manager (WHM) tool, which makes it easy to keep track of your client websites.

Plus, you can white label the hosting to create a branded experience for your customers.

The reseller plans also include free account migration, SSL certificates, automated backups, and a CDN.

Pricing: A2 Hosting reseller plans start at $24.99 per month when paid yearly, and include 60 GB of disk space, a money-back guarantee, and more.

For more details, see our detailed A2 Hosting review for an in depth look at the hosting features, performance, and plans.

6. InMotion

InMotion Reseller

InMotion is a popular host that offers reliable performance for business websites. The technical support team is very helpful, plus there’s 99.99% guaranteed uptime.

Every plan has high bandwidth and disk space to support more websites and traffic at an affordable price.

All plans come with a free cPanel or WHM control panel, root server access, and built-in DDoS and malware protection. This offers your customers flexibility and improved website security.

White label services and billing software are included for free. So, you can easily manage payments while offering customers a hosting experience with your own branding.

If you want to sell domain names too, then you can use the domain reseller account also included in the reseller program.

Pricing: InMotion Hosting reseller plans start at $29.99 per month when paid yearly and offer 80GB storage and support for 25 websites, along with a 90-day money-back guarantee.

To learn more about InMotion, see our in depth InMotion Hosting review where we highlight the performance, speed, and pros and cons.

What is the Best Reseller Hosting? (Expert Pick)

All of the reseller hosting services above are great choices. The best reseller host for your business will depend on your goals and the kind of websites you’ll be hosting.

If website speed and high quality customer support are important, then SiteGround is the best option.

If you want a beginner-friendly host that your customers can grow and scale their websites with, then HostGator is perfect.

We also looked into other reseller web hosting providers like Liquid Web, GoDaddy, Bluehost, etc but we decided not to list them here to help you avoid choice paralysis.

We hope this article helped you find the best reseller hosting to help you start your own reseller business. You may also want to see our guide on choosing the best website builder and our expert picks on the best business phone services for small businesses.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

The post 6 Best Reseller Hosting Plans of 2021 (Best Value + Quality) appeared first on WPBeginner.

Monetize Open-Source Software With Gatsby Functions And Stripe

In this article, I’ll be explaining how I’ve used Gatsby Functions and the Stripe API to enable secure “Pay what you want” contributions that help fund my open-source project MDX Embed.

Note: MDX Embed allows you to easily embed popular third-party media content such as YouTube videos, Tweets, Instagram posts, Egghead lessons, Spotify, TikTok and many more straight into your .mdx — no import required.

Gatsby Serverless Functions

Gatsby Functions open up a whole new world for front-end developers as they provide a way to write and use server-side code without the hassle of maintaining a server. Uses for Serverless Functions range from Newsletter signups with ConvertKit, sending an email using SendGrid, saving data in a database like Fauna, or in this case, accepting secure payments using Stripe — the list is quite frankly endless!

Third-party services like the ones mentioned above will only accept requests that are sent server-side. There’s a number of reasons for this but using secure or private keys is typically one. Using these keys server-side means they’re not exposed to the client (browser) and can’t be abused, and it’s here where Gatsby’s Serverless Functions can help.

Gatsby provides the same logical approach to Serverless Functions as they do with pages. For example, website pages are located in src/pages and Serverless Functions are located in src/api.

Naturally, there’s slightly more to it than that but Gatsby’s developer experience is both logical and consistent, and I for one absolutely love that!

Same Origin Functions

Nine times out of ten when working with Serverless Functions you’ll be using them the way they were supposed to be used, E.g, your website uses its own functions. I call this usage Same Origin Functions or SOF’s for short. In this scenario both the Front-end and the API are deployed to the same origin, E.g www.my-website.com, and www.my-website.com/api, and communication between the two is both seamless and, of course, blazing fast!

Here’s a diagram to help illustrate what that looks like:

Cross-Origin Functions

There are, however, at least two scenarios I’ve encountered where I’ve needed what I’ve been calling “Cross-Origin Functions” (or COF’s for short). The two scenarios where I’ve needed COF’s are as follows:

  1. I need server-side capabilities but the origin website can’t run Serverless Functions.
  2. The Serverless Function is used by more than one origin.

Note: Using Gatsby isn’t the only way to write Serverless Functions but more on that in a moment.

I first experimented with this approach in November 2020 before the release of Gatsby Functions and used Netlify Functions to provide server-to-server communications with the Twitter API and my Gatsby blog and commercial portfolio. You can read about this approach here: Use Netlify Functions and the Twitter API v2 as a CMS for your Gatsby blog.

After the release of Gatsby Functions in June 2021 I refactored the above to work with Gatsby Functions and here’s a little more information about how I went about it and why: Using Gatsby Functions as an abstracted API.

Here’s a diagram to better illustrate the general approach.

In the above diagram website-1.com is built with Gatsby and could have used Serverless Functions (but doesn’t) and website-2.com is built using something that has no Serverless Function capabilities.

Note: In both cases, they both need to use the same third-party service so it makes sense to abstract this functionality into a standalone API.

The example standalone API (my-api.com) is also a Gatsby site and has Serverless Function capabilities, but more importantly, it allows websites from other origins to use its Serverless Functions.

I know what you’re thinking: CORS! Well, sit tight. I’ll cover this shortly.

💰 Monetizing MDX Embed

This was the situation I found myself in with MDX Embed. The documentation website for this project is built using Storybook. Storybook has no serverless capabilities but I really needed server-to-server communication. My solution? I created a standalone API called Paulie API.

Paulie API

Paulie API (like the example standalone API mentioned above) can accept requests from websites of different origins and can connect to a number of different third-party services, one of which is Stripe.

To enable Stripe payments from MDX Embed, I created an api/make-stripe-payment endpoint on Paulie API which can pass the relevant information from MDX Embed through its own Serverless Function and on to the Stripe API to create a “checkout”. You can see the src code here.

Once a checkout has been successfully created, the Stripe API returns a URL. This URL is passed back to MDX Embed which opens a new window in the browser where “customers” can securely enter their payment details on a Stripe webpage... and boom! You get paid!

Here’s a diagram that better illustrates how this works:

This approach is the same as mentioned above where https://mdx-embed.com sends requests to https://paulieapi.gatsbyjs.io which in turn connects to the Stripe API using server-to-server communication. But before we go too much further, it’s worth explaining why I didn’t use react-stripe-js.

react-stripe-js

react-stripe-js is a client-side (browser) toolkit that allows you to create Stripe checkouts and elements in your React project. With react-stripe-js you can set up a method for accepting payments securely without the need for server-side communication, but… and there is a but. I wanted to implement “Pay what you want” contributions. Allow me to explain.

Here’s a screenshot of the MDX Embed “product” that I’ve set up in my Stripe dashboard. Notice the price is $1.00.

If I’d used react-stripe-js to enable payments all “customers” would be asked to pay the same amount. In this case, it’s only $1.00 and that’s not gonna pay the bills is it!

To enable “Pay what you want” (e.g. a nominal amount chosen by a “customer”), you have to dive a little deeper and use server-to-server communication and send this amount to the Stripe API using a custom HTTP request. This is where I'm using a Gatsby Function and I pass in a dynamic value which will then be used to create the “checkout” experience and overwrite the price defined in my Stripe dashboard.

On MDX Embed, I’ve added an HTML <input type="number" /> which allows “customers” to set an amount rather than paying a predefined amount — if only all e-commerce were like this!

Here’s a little video I made that shows how MDX Embed, Paulie API and the Stripe API all work together:

You should see from the above diagram that http://paulie.dev also uses the Stripe endpoint. I’ve used the same approach as with MDX Embed to enable the “Pay what you want” functionality. It’s a small thing, but since the make-stripe-payment endpoint is already written and working, I can re-use it and avoid duplicating this functionality.

The http://paulie.dev website also has its own Gatsby Serverless Functions which I use to post user reactions to Fauna and capture Newsletter signups. This functionality is unique to this site so I haven’t abstracted this yet. However, if I wanted newsletter sign-ups on https://www.pauliescanlon.io, this would be the point where I migrate the function over to Paulie API.

Abstraction

This might seem like a step backwards to abstract your Serverless Functions. After all, one of the coolest things about going serverless is that both your front and back-end code are live in the same place. As I’ve shown, there are times where abstracting makes sense — to me anyway.

I’m certainly benefitting from using this approach and plan to further develop my API to provide more functionality to a number of my own websites, but if making money from open-source is of interest to you and your site isn’t built using Gatsby, this approach may well be the answer you were looking for.

Wanna get started with Gatsby Functions? Check out the Gatsby Functions docs to get going!

Further Reading

If you’re interested in learning more about Serverless Functions I’d recommend:

FuncJam

From August 17 to September 30, the Gatsby folks are running a community competition with some absolutely mega prizes to be won. If there’s still time, then pop on over to FuncJam and join in. Also, check out the Byte-size section of this blog post; it contains helpful videos and links to a number of example functions.

Thanks for reading, and if you’d like to discuss anything mentioned in this article, leave a comment below or find me on Twitter.

Dagger 2 – Constructor Dependency Injection in Kotlin

Introduction

In Android development, the current recommended library for Dependency Injection is Hilt. The most obvious benefits of using Hilt are reduced boilerplate code and lifecycle-aware components(and their associated annotations).

Hilt is a great library, but it is not perfect. Hilt is built on top of Dagger 2, so the terminologies and concepts are hard to understand for developers who did not use Dagger before being introduced to Hilt.

This tutorial introduces Dagger 2 in its original form using Kotlin to make it easy for Kotlin-only developers to follow. The main feature that we are going to look at in this tutorial is constructor dependency injection using Dagger 2.

Goals

At the end of this tutorial, you would have learned:

  1. How to use Dagger constructor injection.
Prerequisite Knowledge
  1. What dependency injection is.
  2. Basic Kotlin.
Tools Required
  1. IntelliJ Community Edition.
Project Setup

First we need to set up our Kotlin project:

  1. In IntelliJ, go to File > New > Project.
  2. In the New Project wizard:
    a. Select Kotlin on the left hand side.
    b. Use Dagger2Practice as project name(optional).
    c. You can leave the Location as default if you wish.
    d. Project Template is Application.
    e. Build System is Gradle Kotlin.
    f. Project JDK is set at Java 11. I find this version to be most stable when working with Kotlin.
    g. Group ID is com.example.
    h. Artifact ID is Dagger2Practice.
    i. Version is 1.0-SNAPSHOT.
    j. This is how the project setting looks like:

Untitled.png

  1. Click Next.

  2. Leave the next screen as default and click Finish. Wait a few seconds for the project to build.

  3. Copy and paste this exact same gradle configuration below into your build.gradle.kts file.

     import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
    
     plugins {
        kotlin("jvm") version "1.5.30"
        kotlin("kapt") version "1.5.30"
     }
    
     group = "com.example"
     version = "1.0-SNAPSHOT"
    
     repositories {
        mavenCentral()
        google()
     }
    
     dependencies {
        kapt("com.google.dagger:dagger-compiler:2.38.1")
        implementation("com.google.dagger:dagger:2.38.1")
        testImplementation("org.jetbrains.kotlin:kotlin-test:1.5.21")
     }
    
     tasks.test {
        useJUnitPlatform()
     }
    
     tasks.withType<KotlinCompile>() {
        kotlinOptions.jvmTarget = "1.8"
     }
  4. In your IDE, go to Build -> Build Project. This will bring in necessary libraries and annotation processing for your project.

  5. Under the kotlin directory, create the packages below. Later on, we will put Dagger boilerplate code in them.

     com.example.component
     com.example.module
  6. Create a new file Entry.kt under the package com.example. This is where your main function lives, so create a main() function here.

  7. To be able to use DI, we are going to need an object that depends on some other objects. Under the package com.example, create a data class called Store. Store will depend on two other classes that we will tell Dagger to inject them at runtime. Copy the source code below into Store.kt. Dont worry if the code does not compile for now.

     package com.example;
    
     import javax.inject.Inject
    
     data class Store
     @Inject constructor
        (val manager: Manager,
         val employee: Employee)
  8. Under the com.example package, create a Manager interface. Copy the code below into Manager.kt.

     package com.example
    
     interface Manager
  9. Also under com.example, create a data class called Employee. This data class has one string field to store the employee name.

     package com.example
    
     data class Employee(val name: String)
Concept Overview

For Dagger to create a Store object at runtime, we have to configure the whole dependency graph, teaching Dagger how to construct objects with configurable constructors or instances of interfaces.

dager2.png

At the top of a dependency graph is a Component. A Component is an interface with an abstract function returning the type of the instance we want (Store in this case). We can provide Modules to a Component to help it complete its dependency graph.

A Module here is not a gradle or Java module. It is a class/interface that contains functions providing the dependency objects at runtime. Have you noticed that Manager is an interface and Employee is a configurable class? Dagger requires the developer to teach it how to provide instances for both.

Employee Module

Let us satisfy Daggers requirements one by one, starting with an argument of type Employee for the Store class.

Under com.example.module, create an EmployeeModule abstract class.

    package com.example.module

    import com.example.Employee
    import dagger.Module
    import dagger.Provides

    @Module //1
    abstract class EmployeeModule {

       companion object { //2
           @Provides //3
           fun provideEmployee() = Employee("Anna") //4
       }

    }

Here are the explanations for the code above:

  1. The @Module annotation at line 1 marks the class as a Dagger module.
  2. We put the function that provides an Employee inside a companion object to make static and Dagger does not have to instantiate EmployeeModule at runtime.
  3. The @Provides annotation marks the function as a function that provides a dependency object instance.
  4. The function provideEmployee() returns an Employee of the name Anna at runtime. By convention, the method name for a @Provides annotation should start with provide.
Manager Module

Now that we are finished with the EmployeeModule, we have to teach Dagger how to provide an instance of Manager next.

Lets not use the @Provides annotation again. Dagger has another annotation that is @Binds. @Binds works differently to @Provides. A @Binds function is abstract and binds the function argument as the return value.

Under com.example.module, create a ManagerModule interface.

    package com.example.module

    import com.example.Manager
    import com.example.ManagerImpl
    import dagger.Binds
    import dagger.Module

    @Module //1
    interface ManagerModule { //2

       @Binds //3
       fun bindManager(managerImpl: ManagerImpl): Manager //4

    }

As you can see, the function bindManager takes a ManagerImpl argument (that we have not created yet). This ManagerImpl type must be on the dependency graph and it must implement Manager. Under com.example, create a ManagerImpl class that implements Manager.

    package com.example

    import javax.inject.Inject

    class ManagerImpl @Inject constructor(): Manager

Notice that the constructor of ManagerImpl is an empty no-args constructor marked with @Inject. Dagger knows that this class can be instantiated by calling the empty constructor, which will make it easy for it to pass into the bindManager() function defined previously.

Store Component

Now that we have configured both of the Modules in the dependency graph, the final step is to declare the StoreComponent.

Under com.example.component, create an interface called StoreComponent.

    package com.example.component

    import com.example.Store
    import com.example.module.EmployeeModule
    import com.example.module.ManagerModule
    import dagger.Component

    @Component(modules = [ManagerModule::class, EmployeeModule::class]) //1
    interface StoreComponent { //2
       fun store(): Store //3
    }  

A Component needs to be annotated with @Component. This annotation takes a list of class objects for the Modules. By passing in the module classes, we declare that these modules can be used to generate an implementation of StoreComponent. The implementation class will be prefixed with Dagger and the rest of the class name is the same as the interface name.

Go back to our main function (in Entry.kt), and copy the code below into your IDE.

    import com.example.Store
    import com.example.component.DaggerStoreComponent

    fun main(){
       val store: Store = DaggerStoreComponent.create().store()
       println(store.employee)
       println(store.manager)
    }

To get an instance of Store, we simply call the Dagger-generated implementation DaggerStoreComponent -> create() -> store().

store() is the abstract function that we declared earlier.

You might have to go to Rebuild the project for the generated class to show up and for your code to compile.

Solution Code

The full project code can be found here https://github.com/dmitrilc/DaniWebDagger2Constructor/tree/master

Summary

If you look at the final source code folder, you might have noticed that we created quite a lot of boilerplate code just for Dagger: 2 modules and one component. Dagger 2 is somewhat complex to set up, but it is worth it for large projects.

How to create Repeatable Annotations in Java

Introduction

In Java 8, @Repeatable was introduced and this is the recommended way to create repeating annotations. We still have to create a holder Annotation(annotation that holds an array of other annotations), but we no longer have to declare the holder Annotation at the callsite.

This tutorial aims to show you the difference between the old way and the new way using @Repeatable.

Goals

At the end of this tutorial, you would have learned:

  1. How to create your own custom Annotations.
  2. How to create repeatable Annotations.
Prerequisite Knowledge
  1. Basic Java
  2. Basic knowledge of Reflection API.
  3. Basic understanding of Annotations.
Tools Required
  1. A Java IDE with at least JDK 8 support.
Project Setup

To follow along with this tutorial, perform the steps below:

  1. Create a new Java project.
  2. Create a package com.example.
  3. Create a Java class called Entry.java. This is where our main() method lives.
  4. Under the com.example package, create 3 public classes:
    a. Banana
    b. Cat
    c. Bike
Custom Annotation Review

Most Java developers I met have told me that they never had to create their own custom Annotations, even though they use Annotations every day(@Override). It is usually the job of frameworks to provide out-of-the-box Annotations for other developers to use.

This section of the tutorial provides a quick overview of how to create custom Annotations for those who are not familiar with the syntax or as a review for those who have forgotten.

Copy and paste the code below into your Cat.java file.

    package com.example;

    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;

    @Retention(RetentionPolicy.RUNTIME)
    @interface CatAttribute { //1
       String value(); //2
    }

    @CatAttribute("Cute") //3
    public class Cat { } //Single custom Annotation

In the code snippet above, we declared an empty class Cat and an Annotation called CatAttribute.

Annotations are similar to interfaces. They are implicitly abstract and cannot be instantiated. That is why the chosen syntax for declaring an annotation is also the keyword interface, but prefixed with an @ symbol to differentiate between the two.

Annotations that we see in code might not survive compile-time or runtime. Whether they are stripped or preserved at different stages is determined by the enum RetentionPolicy(CLASS, RUNTIME, SOURCE).

You are not required to annotate your custom Annotations with @RetentionPolicy; I only do that for this code snippet because later we are going to retrieve the annotation in main(). If you do not annotate your custom Annotation with @RetentionPolicy, then your annotation will just follow the default behavior, which is specified by RetentionPolicy.CLASS.

Pay attention to the value() method at line 2. The method value() is special, and the terminology changes a little bit. The official documentation calls them elements instead of methods. If the special element value exists in an Annotation, then we do not have to specify the word value again at the callsite, hence why we were able to pass Cute directly to @CatAttribute at line 3.

The old way of creating repeating Annotations

For us to understand how to use @Repeatable, we need to see how the old way works first .

Copy and paste the code below into Banana.java.

    package com.example;

    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;

    @interface Benefit { //1
       String value();
    }

    @Retention(RetentionPolicy.RUNTIME)
    @interface Benefits { //2
       Benefit[] value(); //3
    }

    @Benefits({ //4
           @Benefit("Nutritious"), //5
           @Benefit("Healthy") //6
    })
    public class Banana { } //The old way to doing repeatable annotation

In the code snippet above, we have created two different Annotations. The Benefit Annotation is what contains interesting information for the class Banana, but the Benefits(plural) Annotation contains an array to hold the other Benefit Annotations.

At callsite at line 4, the code becomes a little bit hard to read because we have to declare the holder annotation and the holder array as well. Wouldnt it be nice to just be able to apply multiple Benefit Annotations directly to Banana instead?

@Repeatable Annotation

The @Repeatable Annotation allows you to do just that. After setting it up, we will be able to apply the same Annotation multiple times.

In Bike.java, copy and paste the code below:

    package com.example;

    import java.lang.annotation.Repeatable;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;

    @Repeatable(BikeAttributes.class) //1
    @interface BikeAttribute { //2
       String value();
    }

    @Retention(RetentionPolicy.RUNTIME)
    @interface BikeAttributes { //3
       BikeAttribute[] value(); //4
    }

    @BikeAttribute("Agile") //5
    @BikeAttribute("Affordable") //6
    public class Bike { } //Repeatable annotation

To use @Repeatable, we have to perform the almost exact steps as when we were using the holder Annotation. The only extra step that we have to do is to annotate the Annotation that needs repeating with @Repeatable and pass in the class of the holder Annotation as its value. You can see that at line 1.

Even though it is just sugar syntax, the benefit here is that we no longer have to declare the holder Annotation anymore, and can annotate the @BikeAttribute directly multiple times.

What do Annotations look like at runtime?

Since we annotated all of the Annotations that we created in the previous steps with @Retention(RetentionPolicy.RUNTIME), we are now able to retrieve them at runtime. In your Entry.java class, copy and paste the code below.

    package com.example;

    import java.lang.annotation.Annotation;

    public class Entry {
       public static void main(String[] args){
           Annotation[] catAnnotations = Cat.class.getAnnotations(); //1 getting cat annotations via reflection
           for (Annotation annotation : catAnnotations) {
               System.out.println(annotation);
           }

           Annotation[] bananaAnnotations = Banana.class.getAnnotations(); //2 getting banana annotations via reflection
           for (Annotation annotation : bananaAnnotations){
               System.out.println(annotation);
           }

           Annotation[] bikeAnnotations = Bike.class.getAnnotations(); //3 getting bike annotations via reflection
           for (Annotation annotation : bikeAnnotations){
               System.out.println(annotation);
           }
       }
    }

All the code does is to get the Annotations that were preserved at runtime for our previous classes and print them out.

For the Cat class that was only annotated once, we get:

    @com.example.CatAttribute("Cute")

But for both Banana and Bike classes, they both get the holder Annotations, which further proves that @Repeatable is just sugar syntax.

    @com.example.Benefits({
    @com.example.Benefit("Nutritious"), 
    @com.example.Benefit("Healthy")
    })
    @com.example.BikeAttributes({
    @com.example.BikeAttribute("Agile"),
     @com.example.BikeAttribute("Affordable")
    })
Solution Code

You can find the full source code for the project here https://github.com/dmitrilc/DaniwebJavaRepeatable

Summary

We have learned how to create repeatable Annotations. Its sugar syntax will make our code a lot more readable.

The @Repeatable syntax also makes it very easy to convert current holder Annotations. All you have to do is to add @Repeatable to child Annotation and pass in the class object of the holder Annotation.