4

I have barcode generator methods that I call from Controller in my Java (Spring Boot) project. The generator class is as shown below:

@Component
@NoArgsConstructor
public class QRCodeGenerator {
    private static final int LABEL_X_POS = 45;
    private static final int LABEL_Y_POS = 20;

    @Value("${qr-code.margin}")
    private int margin;

    @Value("${qr-code.fontSize}")
    private int fontSize;

    public ResponseEntity<Resource> getQRCode(String data) throws IOException {
        
        // code omitted for brevity
        
        addLabel(image, label);        
        final ByteArrayResource resource = new ByteArrayResource(toByteArray(image));
        return ResponseEntity.ok().body(resource);
    }

    private static byte[] toByteArray(BufferedImage image) throws IOException {
        // code omitted for brevity
    }

    private void addLabel(BufferedImage source, String text) {
        int x = LABEL_X_POS;
        int y = LABEL_Y_POS;
        // code omitted for brevity
    }
}

First I started to use this class as static, but then I removed static to read the data in application.yml properly.

Here is some points that I need to be clarified:

1. I am new in Spring and as far as I see, spring services are generally used to provide data from database or any other service, endpoints, etc. Is that true?

2. Should I create a service for the class above (I do not need to access to database in that class)? Or it the approach is better (creating as a component and then injecting it to my Controller)?

3. There are many different opinions regarding to static Util classes. So, what about converting this class to a static Util class? Is it better than now or using it as a Spring Service?

3 Answers3

2

Make it a spring service, and you will be able to substitute a mock for it easily when you write a test for the controller. Otherwise you will not be able to mock it (unless you use things like Powernock). Since you're already injecting values into it, it's a lot easier to keep this as a Spring component.

Generally it's a premature optimization to use static util classes and it can get in the way of testing. I would use static util classes only if they contain only static methods that have no side effects, which don't need access to configuration data and which I don't mind not being able to mock. The methods I use in input validation code would be an example of something I might use static methods for. But you have the most flexibility, for instance to be able to inject configurations, if you keep these as Spring components.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • **1.** Thanks a lot for your detailed answers. In this case I should create a Spring Service for my `QRCodeGenerator` class. On the other hand, I am wondering what is the difference keeping this as `@Component` and replacing this annotation to `@Service`. As the latter is also a component, is the only difference making it more specific? –  Dec 18 '21 at 20:08
  • **2.** What about Util classes in Spring? Assume that I have several methods e.g. `formatDate()`, `convertToBinary()`, etc. SHould I create them in an Util class as static? Or should I still use Service in Spring and keep away from static Util classes? As I have not enough experience in Spring, I need to be clarified about this. Any idea? –  Dec 18 '21 at 20:10
  • @binary: service annotation doesn't really do anything more than component,, it mainly is there to tell you what layer of the application the component belongs to. – Nathan Hughes Dec 18 '21 at 20:11
  • @binary: I think it's fine to avoid util classes and use spring components instead. Spring wants to control how things are created but for util classes the classloader is in charge, so they don't mix well. Let spring be in charge. – Nathan Hughes Dec 18 '21 at 20:14
  • Thanks a lot, I would not think to keep away Static Utils as there are several ones in our project, but as you suggest, I will keep in mind that and always try to use service (@Service). I think this is the better approach, isn't it? –  Dec 18 '21 at 20:17
  • @binary: i think making these things spring components is better for maintainability since it lets you add dependencies if needed. When we used xml configuration it was more of a hassle to make everything a spring bean but it's painless now. – Nathan Hughes Dec 18 '21 at 20:22
  • Thanks a lot, I use annotation, not xml configuration. What about this question? >>> –  Dec 18 '21 at 20:30
  • On the other hand, as far as I understood, keeping the code above in a util package with `@Component` annotation is almost the same think as keeping it in a service package with `@Service` annotation. Any idea? –  Dec 18 '21 at 20:30
1

Here are some opinions on your questions:

  1. Classes annotated with @Service are used in business logic layer, it can provide data but it can also do actions as in your case.
  2. Based on the point 1. you can make it a service because that provides logic for creating qr codes for representation layer (Controllers).
  3. Having this kind of classes as @Component or more specific @Service makes it easier to inject dependencies using Dependency Injection and also it's easier to inject your class as dependency to other beans so it's easier also to test/mock. Keeping it as Spring Service is a better approach.
Granit Krasniqi
  • 151
  • 1
  • 6
  • **1.** Thanks a lot for your detailed answers. In this case I should create a Spring Service for my `QRCodeGenerator` class. On the other hand, I am wondering what is the difference keeping this as `@Component` and replacing this annotation to `@Service`. As the latter is also a component, is the only difference making it more specific? –  Dec 18 '21 at 20:08
  • **2.** What about Util classes in Spring? Assume that I have several methods e.g. `formatDate()`, `convertToBinary()`, etc. SHould I create them in an Util class as static? Or should I still use Service in Spring and keep away from static Util classes? As I have not enough experience in Spring, I need to be clarified about this. Any idea? –  Dec 18 '21 at 20:10
  • 1. Yes, the difference is only making it more specific and indicating that it provides business logic for other clients to use such as (Controllers). 2. Your classes should comply to Single Responsibility Principle and have well defined interface (methods), it's easier to achieve this by creating `@Component` or `@Service` (Service if it provides business logic) because they are easier to test and use in spring. Util classes are not a best practice because they are harder to mock and can degrade to having multiple responsibilities. – Granit Krasniqi Dec 18 '21 at 20:15
  • Thanks a lot, I learned a lot –  Dec 18 '21 at 20:20
0

Short answer: user Spring Service (or Component) and avoid the use of Util classes with static methods. This way you will live happy life without Tight Coupling and Fragile Code

https://www.geeksforgeeks.org/coupling-in-java/

https://stackoverflow.com/a/76304657/4776689

Regrding your 3 questions:

  1. I am new in Spring and as far as I see, spring services are generally used to provide data from database or any other service, endpoints, etc. Is that true?

Yes it is true, but you also can create Spring beans like @Service or @Component for any general functionality

  1. Should I create a service for the class above (I do not need to access to database in that class)? Or it the approach is better (creating as a component and then injecting it to my Controller)?

Yes you should have Spring bean. It can be Service or Component or any else bean type. I would do with Service.

  1. There are many different opinions regarding to static Util classes. So, what about converting this class to a static Util class? Is it better than now or using it as a Spring Service?

Do not use static Util classes if you can. Spring beans (Service and others) are made to replace them with dependency injection.

P_M
  • 2,723
  • 4
  • 29
  • 62