Table of contents
1.
Introduction
2.
Writing Play Modules
3.
Module Registration
4.
Testing Play Modules
5.
Overriding Built-In Modules
6.
Writing Plugins
7.
Frequently Asked Questions
7.1.
What are some of Scala's key characteristics?
7.2.
Name some of the frameworks that Scala supports.
7.3.
What do Scala case classes do?
8.
Conclusion
Last Updated: Mar 27, 2024

Scala developers-Extending Play

Author Shivani Singh
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

An improved version of Java called Scala was created to get rid of extraneous code. It supports a variety of libraries and APIs, allowing the programmer to work with less downtime. Because Scala provides various types of Constructs, programmers can easily interact with wrapper and container types.

Scala developers-Extending Play

In one succinct, high-level language called Scala, object-oriented and functional programming are combined. Static types in Scala help prevent errors in complicated applications, and the JVM and JavaScript runtimes enable you to easily access vast ecosystems of libraries for developing high-performance systems.

Data processing, distributed computing, and web development all employ Scala. Many businesses use it to power their data engineering infrastructure.

Writing Play Modules

Writing Play Modules

Any framework for dependency injection can be used to create modules. In order for your extension to function independently of the dependency injection, you must avoid dependencies on certain frameworks when you want to extend Play. The play originally accomplished this using the play. api.Plugin system, but as of version 2.5.x, Play modules have taken the role of Plugins. Rather than expressly relying on a specific dependency injection framework, a Play module is a class that extends play. api. inject. Module and may be registered with Play. This makes Play modules available to all users.

The module directory contains a list of Play modules. Additionally, a Play module must be utilized to replace or supplement built-in functionality because Play employs Play modules for built-in functionality.

Creating a play module is very simple. It's like making a cup of tea.

Let's see how is it done:

class MyCode {
  // add functionality here
}
class MyModule extends play.api.inject.Module {
  def bindings(environment: Environment, configuration: Configuration) = {
    Seq(bind[MyCode].toInstance(new MyCode))
  }
}


These are simple lines of code and you are done with creating a play module.

Module Registration

In this section of the blog, we will see how to do the module registration in Scala. Any class named Module defined in the root package (the "app" directory),  will be loaded by default by Play or specifically defined inside the reference. conf or the application.conf: 

play. modules.enabled += "modules.MyModule"


To know about the application lifecycle, by infusing the play.api.inject.ApplicationLifecycle trait and a shutdown hook into the singleton instance, a module can track when Play shuts down.

Testing Play Modules

Modules can be tested using the GuiceApplicationBuilder, Play's built-in test capabilities, or by adding a binding to the module.

Testing Play Modules
val application = new GuiceApplicationBuilder()
  .bindings(new MyModule)
  .build()
val myCode = application.injector.instanceOf(classOf[MyCode])
myCode must beAnInstanceOf[MyCode]


For listing the existing play modules: A list of all Play modules that are available in an application will be shown using the Modules.locate(env, conf) method.

Overriding Built-In Modules

In some circumstances, a built-in module provided by Play needs to be overridden.

For instance, the MessagesApi trait, which is supported by DefaultMessagesApi, implements the Messages feature. You can bind a substitute class called MyMessagesApi, which extends MessagesApi, with:

class MyI18nModule extends play.api.inject.Module {
  def bindings(environment: Environment, configuration: Configuration) = {
    Seq(
      bind[Langs].toProvider[DefaultLangsProvider],
      bind[MessagesApi].toProvider[MyMessagesApiProvider]
    )
  }
}


For testing overrides:

The overrides function should be used to test the application in place of the current implementation:

val application = new GuiceApplicationBuilder()
  .overrides(new MyI18nModule)
  .build()

For Registration Overrides:

Since reference. conf loads the I18nModule automatically, you must first remove the default module before adding the new module:

play. modules.disabled += "play.api.i18n.I18nModule"
play. modules.enabled += "modules.MyI18nModule"


When uploading a Play module, you shouldn't disable any existing modules in reference. conf because doing so can have unintended effects.

Writing Plugins

The play. api.Plugin API was deleted in version 2.5 after being deprecated in version 2.4.x.

If you have developed a Play plugin, you should think about switching from the obsolete Java play. Plugin or Scala play. api.Plugin types to play.api.inject.Module. The primary distinction between the new Module API and the previous Plugin API is that with the latter, we will openly embrace Dependency Injection (DI).

In order to load a plugin using the previous Plugin API, a play. plugins file containing a number and the plugin's fully qualified name was necessary. Play utilized the number to establish the overall order of the plugins. The dependencies of the plugin were initialized before the plugin itself since this method was brittle because it was challenging to ensure that the number matched the appropriate position in the startup order. Furthermore, there was no method to prevent the usage of the same number by two plugins. Using DI, both issues have been resolved. Components are now initialised in the function Object() { [native code] } and explicitly declare their dependencies as function Object() { [native code] } parameters.

Frequently Asked Questions

What are some of Scala's key characteristics?

Some of Scala’s key features are Type Inference, Immutability Lazy Evaluation, Case classes and Pattern matching, String Interpolation, and Singleton object.

Name some of the frameworks that Scala supports.

A few of the frameworks that Scala supports are Frameworks like the Neo4j Framework, Spark Framework, Play Framework, Akka Framework, etc.

What do Scala case classes do?

Case classes in Scala are similar to regular classes, with the exception that they are useful for representing immutable data and pattern matching. Case classes by default include immutable and public parameters. Because these classes provide pattern matching, writing logical code is much simpler.

Conclusion

To conclude this blog, firstly we discussed some basics about Scala, writing play modules, and module registration. We also saw testing play modules, overriding built-in modules, and writing plugins. 

For more content, Refer to our guided paths on Coding Ninjas Studio to upskill yourself.

Do upvote our blogs if you find them helpful and engaging!

Happy Learning!

Thankyou
Live masterclass