DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4
  • How Spring Boot Starters Integrate With Your Project
  • A Practical Guide to Creating a Spring Modulith Project
  • Structured Logging in Spring Boot 3.4 for Improved Logs

Trending

  • How To Develop a Truly Performant Mobile Application in 2025: A Case for Android
  • Endpoint Security Controls: Designing a Secure Endpoint Architecture, Part 1
  • Unmasking Entity-Based Data Masking: Best Practices 2025
  • Beyond Simple Responses: Building Truly Conversational LLM Chatbots
  1. DZone
  2. Coding
  3. Frameworks
  4. Deep Learning with Spring Boot and DJL

Deep Learning with Spring Boot and DJL

In this tutorial we review how to create a sample Deep Learning Java app using Spring Boot, DJL and Tensorflow.

By 
David Kiss user avatar
David Kiss
·
Jun. 03, 20 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
13.4K Views

Join the DZone community and get the full member experience.

Join For Free

Overview

This is another post on Spring Boot that will show how to build a sample web application using Deep Java Library (DJL), an open-source Deep Learning library for Java to diagnose COVID-19 on X-ray images.

The sample app is a Spring Boot based version of DJL's similar COVID-19 example and it has a simple static HTML page built using Twitter Bootstrap and JQuery where users can submit an image URL to a REST api where the DJL library will download the image and predict if it's an X-ray image of lungs infected with COVID-19 or not.

The link to the source code is included at the end of this post.

Disclaimer: This is only a demo application based on the dataset at https://github.com/ieee8023/covid-chestxray-dataset and it SHOULD NOT be used for actual medical diagnosis.

Deep Java Library

As mentioned earlier, DJL is a Java-based library that supports multiple
Deep Learning frameworks like Apache MxNet, PyTorch and Tensorflow. Since most Deep Learning engines are built using Python and not in Java, DJL built engine adapters to access each of these engines’ native shared library.

DJL does it in an elegant way making it dead simple to switch from one framework to the other depending on the use case.

Dependencies

The app needs the Spring Boot web starter:

Java
 




x


 
1
        <dependency>
2
            <groupId>org.springframework.boot</groupId>
3
            <artifactId>spring-boot-starter-web</artifactId>
4
        </dependency>


And the commons-io library for some basic I/O operations:

Java
 




xxxxxxxxxx
1


 
1
       <dependency>
2
            <groupId>commons-io</groupId>
3
            <artifactId>commons-io</artifactId>
4
            <version>2.6</version>
5
       </dependency>


The Lombok library, too, as I'm too lazy to write the getters and setters:

Java
 




xxxxxxxxxx
1


 
1
       <dependency>
2
            <groupId>org.projectlombok</groupId>
3
            <artifactId>lombok</artifactId>
4
            <optional>true</optional>
5
       </dependency>


And finally the DJL dependencies for this sample app:

Java
 




xxxxxxxxxx
1
27


 
1
       <dependency>
2
            <groupId>ai.djl</groupId>
3
            <artifactId>api</artifactId>
4
            <version>${ai.djl.version}</version>
5
       </dependency>
6
       <dependency>
7
            <groupId>ai.djl.tensorflow</groupId>
8
            <artifactId>tensorflow-api</artifactId>
9
            <version>${ai.djl.version}</version>
10
       </dependency>
11
       <dependency>
12
            <groupId>ai.djl.tensorflow</groupId>
13
            <artifactId>tensorflow-engine</artifactId>
14
            <version>${ai.djl.version}</version>
15
       </dependency>
16
       <dependency>
17
            <groupId>ai.djl.tensorflow</groupId>
18
            <artifactId>tensorflow-native-auto</artifactId>
19
            <version>${tensorflow-native-auto.version}</version>
20
            <scope>runtime</scope>
21
       </dependency>
22
       <dependency>
23
            <groupId>net.java.dev.jna</groupId>
24
            <artifactId>jna</artifactId>
25
            <version>${jna.version}</version>      <!-- overrides default spring boot version to comply with DJL -->
26
       </dependency>
27

          


Here's the list of Maven properties needed for the DJL dependency versions:

Java
 




xxxxxxxxxx
1


 
1
   <properties>
2
        <java.version>1.8</java.version>
3
        <ai.djl.version>0.5.0</ai.djl.version>
4
        <jna.version>5.3.0</jna.version>
5
        <tensorflow-native-auto.version>2.1.0</tensorflow-native-auto.version>
6
   </properties>


XRayApplication class

This class's main() method will fire up the Spring Boot application and it looks like most other Application class files:

Java
 




xxxxxxxxxx
1


 
1
@SpringBootApplication public class XRayApplication { 
2
    public static void main(String[] args) {
3
         SpringApplication.run(XRayApplication.class, args);
4
    } 
5
}


Configuration

In order to configure the DJL library, let's create a DjlConfig class with the @Configuration annotation.

This class will define a ZooModel Spring Bean that will help predicting if the submitted image URL belongs to a COVID-19 infected lung:

Java
 




xxxxxxxxxx
1


 
1
    @Bean
2
    public ZooModel xrayModel() throws Exception {
3
        Criteria<BufferedImage, Classifications> criteria =
4
                Criteria.builder()
5
                        .setTypes(BufferedImage.class, Classifications.class)
6
                        .optTranslator(new XrayTranslator())
7
                        .build();
8
        return ModelZoo.loadModel(criteria);
9
    }


What this code says is that we create a ZooModel object with a BufferedImage input and Classifications (more on that later) output type and it uses an XrayTranslator object to transform the input images to a format needed by the Deep Learning model to function properly.

Here's the code for the XrayTranslator which is an inner class within DjlConfig:

Java
 




xxxxxxxxxx
1
18


 
1
   public static final class XrayTranslator implements Translator<BufferedImage, Classifications> {
2
         private static final List<String> CLASSES = Arrays.asList("covid-19", "normal");
3

          
4
         @Override
5
         public NDList processInput(TranslatorContext ctx, BufferedImage input) {
6
            NDArray array =
7
                    BufferedImageUtils.toNDArray(
8
                            ctx.getNDManager(), input, NDImageUtils.Flag.COLOR);
9
            array = NDImageUtils.resize(array, 224).div(255.0f);
10
            return new NDList(array);
11
        }
12

          
13
        @Override
14
        public Classifications processOutput(TranslatorContext ctx, NDList list) {
15
            NDArray probabilities = list.singletonOrThrow();
16
            return new Classifications(CLASSES, probabilities);
17
        }
18
    }


Covid19Service

The Covid19Service class will handle the business logic to diagnose the X-ray images and as you'll see, surprisingly, it's really just few lines of code:

Java
 




xxxxxxxxxx
1
17


 
1
@Service
2
public class Covid19Service {
3
    @Autowired
4
    private ZooModel xrayModel;
5

          
6
    public String diagnose(String imageUrl) {
7
        try (Predictor<BufferedImage, Classifications> predictor = xrayModel.newPredictor()) {
8
            Classifications result = predictor.predict(BufferedImageUtils.fromUrl(imageUrl));
9
            return "Diagnose: "
10
                    + result.best().getClassName()
11
                    + " , probability: "
12
                    + result.best().getProbability();
13
        } catch (Exception e) {
14
            throw new RuntimeException("Failed to diagnose", e);
15
        }
16
    }
17
}


The ZooModel bean created in the DjlConfig class is autowired and used in the diagnose()method that has an imageUrl parameter.

Within the method we create a Predictorobject using the try-resource  block (as the predictor needs to be closed after execution) and use it to run the BufferedImage(created using the imageUrl parameter) through a pre-trained Tensorflow model. 

For more details on the model visit: https://www.pyimagesearch.com/2020/03/16/detecting-covid-19-in-x-ray-images-with-keras-tensorflow-and-deep-learning/.

Once the diagnose()method is run, the Classificationsresult object will show if the lungs on the X-ray image were infected with COVID-19 or not and with what probability.

 Covid19Controller 

This controller class defines the REST API to diagnose X-ray images which will be consumed by our simple front-end app:

Java
 




xxxxxxxxxx
1
15


 
1
@RestController
2
@RequestMapping(value = "/api/v1", produces = MediaType.APPLICATION_JSON_VALUE)
3
public class Covid19Controller {
4
    private final Covid19Service covid19Service;
5

          
6
    public Covid19Controller(Covid19Service covid19Service) {
7
        this.covid19Service = covid19Service;
8
    }
9

          
10
    @GetMapping("/covid19/diagnose")
11
    public ResponseEntity diagnose(@RequestParam String imageUrl) {
12
        String answer = covid19Service.diagnose(imageUrl);
13
        return ResponseEntity.ok(Collections.singletonMap("result", answer));
14
    }
15
}


The @RestControllerannotation tells Spring that in our MVC design this is a Controller bean that defines the REST api

The @RequestMappingannotation tells Spring that paths of all REST apis within this class should be prefixed with /api/v1and all REST apis will return application\jsonresponses.

The Covid19Servicethat we discussed earlier is autowired in the constructor and later on used by the diagnose REST api at the GET /api/v1/covid19/diagnosepath.

The diagnose api takes an imageUrlrequest param and returns a JSON document with the String representation of the results.

Front-end

The Spring Boot app has a simple static index.html file as a front-end client for the diagnose REST API and it uses Twitter Bootstrap for the responsive design and JQuery to make the REST API call:

JavaScript
 




xxxxxxxxxx
1


 
1
<head>
2
    <link rel="stylesheet" href="/css/bootstrap.min.css"/>
3
    <script src="/js/jquery.min.js"></script>
4
</head>


The file has an HTML form that can capture an X-ray image URL from the user: 

HTML
 




xxxxxxxxxx
1
10


 
1
       <form id="diagnoseForm" class="mb-4">
2
            <div class="input-group">
3
                <input type="url" id="imageUrl" class="form-control" required
4
                       placeholder="Enter a image url"
5
                       aria-label="Image URL">
6
                <div class="input-group-append">
7
                    <button class="btn btn-outline-primary">Submit</button>
8
                </div>
9
            </div>
10
       </form>


Once the form is submitted, the REST API may take a while to respond. In the meantime the page will show a spinner and once the response is received, the text will be displayed within the diagnose div:

HTML
 




xxxxxxxxxx
1


 
1
       <div class="row ml-1">
2
            <div id="spinnerDiagnose" class="text-primary" role="status">
3
                <span class="sr-only">Loading...</span>
4
            </div>
5
            <div id="diagnose"></div>
6
       </div>


See below the Javascript code:

JavaScript
 




xxxxxxxxxx
1
15


 
1
$( "#diagnoseForm" ).submit(function( event ) {
2
  const imageUrl = $('#imageUrl').val();
3
  $('#spinnerDiagnose').addClass('spinner-border');
4
  $('#diagnose').html('');
5
  $.ajax('/api/v1/covid19/diagnose?imageUrl='+imageUrl)
6
  .done(data => {
7
    $('#spinnerDiagnose').removeClass('spinner-border');
8
    $('#diagnose').html(data.result);
9
  })
10
  .fail(err => {
11
    $('#spinnerDiagnose').removeClass('spinner-border');
12
    $('#diagnose').html('Failed to get answer');
13
  });
14
  event.preventDefault();
15
});


When the form's submit event is triggered, the code gets the imageUrl value, show's the spinner, clears the content of the diagnose div from previous runs and calls the diagnose REST api with the imageUrl.

In case of a successful response the code hides the spinner and displays the results within the diagnosediv.

In case of an error the code also hides the spinner and displays a generic error message.

Running the app

The app needs Tensorflow to be downloaded first before it can be run.

Run the following command in the projects root folder:

Shell
 




xxxxxxxxxx
1


 
1
mkdir models
2
cd models
3
curl https://djl-tensorflow-javacpp.s3.amazonaws.com/tensorflow-models/covid-19/saved_model.zip | jar xv cd .. ./mvnw spring-boot:run -Dai.djl.repository.zoo.location=models/saved_model


Then visit http://localhost:8080/index.html to get diagnose on X-ray image URLs. Sample images to use:

  • COVID-19 infected lungs
  • Normal lungs

Overview

In this tutorial, we reviewed how to create a sample Deep Learning Java app using Spring Boot, DJL, and Tensorflow.

The source code for the post is available at https://github.com/davidkiss/djl-spring-boot-xray.

Spring Framework Spring Boot Deep learning

Published at DZone with permission of David Kiss, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4
  • How Spring Boot Starters Integrate With Your Project
  • A Practical Guide to Creating a Spring Modulith Project
  • Structured Logging in Spring Boot 3.4 for Improved Logs

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!