Gilmar
Gilmar

Reputation: 59

Spring restcontroller with RequestParam String conflcting in controller

I have a Restcontroller with 4 methods, but I can't use the calls, I always get the error: "message": "No static resource api/corp.",

I need method with string like:

and PathVariable methods too

Corp.java

package com.priserp.springapipeta.model;

import jakarta.persistence.*;
import java.util.Objects;

@Entity(name = "corp")
public class Corp {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "corp_id")
    private long id;

    @Column(name = "corp_name")
    private String corpName;

    @Column(name = "corp_fantasy_name")
    private String corpFantasy;

    @Column(name = "corp_cnpj")
    private String corpCnpj;


    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getCorpName() {
        return corpName;
    }

    public void setCorpName(String corpName) {
        this.corpName = corpName;
    }

    public String getCorpFantasy() {
        return corpFantasy;
    }

    public void setCorpFantasy(String corpFantasy) {
        this.corpFantasy = corpFantasy;
    }

    public String getCorpCnpj() {
        return corpCnpj;
    }

    public void setCorpCnpj(String corpCnpj) {
        this.corpCnpj = corpCnpj;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Corp corp = (Corp) o;
        return id == corp.id;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id);
    }

    public Corp(){}
}

CorpRepository.java

@Repository
public interface CorpRepository extends JpaRepository<Corp, Long> {

    @Query("select c from corp c  where c.corpName = :name")
    Corp findByCorpName(@Param("name") String corpName);

    Corp findById(long id);


    Corp findByCorpCnpj(String corpCnpj);
}

CorpController.java

@RestController
@RequestMapping("/api/corp")
public class CorpController {

    private final CorpRepository corpRepository;

    @Autowired
    public CorpController(CorpRepository repository) {
        this.corpRepository = repository;
    }

    @GetMapping("/corps")
    public ResponseEntity<List<Corp>> getAllCorps() {
        System.out.println("listando aqui " +corpRepository.findAll() );
        List<Corp> corps = corpRepository.findAll();
        if (corps.isEmpty()) {
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.ok(corps);
    }

    @GetMapping("/{id}")
    public ResponseEntity<Corp> getCorpById(@PathVariable Long id) {
        System.out.println("by id " + corpRepository.findById(id).get() );
        Optional<Corp> corp = corpRepository.findById(id);
        return corp.map(ResponseEntity::ok)
                .orElseGet(() -> ResponseEntity.notFound().build());
    }

    @GetMapping(value = "/{name}")
    public ResponseEntity<Corp> getCorpByName(@RequestParam(name = "name") String corpName) {
        System.out.println("corpname " + corpName);
        Corp corp = corpRepository.findByCorpName(corpName);
        return ResponseEntity.ok(corp);
    }

    @GetMapping("/{cnpj}")
    public ResponseEntity<Corp> getCorpByCnpj(@RequestParam(name = "cnpj") String corpCnpj) {
        System.out.println("corpCnpj " + corpCnpj);

        Corp corp = corpRepository.findByCorpCnpj(corpCnpj);
        return ResponseEntity.ok(corp);
    }
}

Upvotes: 0

Views: 48

Answers (2)

PPFromInfy
PPFromInfy

Reputation: 189

Although I agree with the solution provided by Hussam Abd ElAziz, I have it a little more optimized.

For below URIs to work:

http://localhost:8090/api/corp?name=PETA

http://localhost:8090/api/corp?cnpj=PETA

@RestController
@RequestMapping("/api/corp")
public class CorpController {

    private final CorpRepository corpRepository;

    @Autowired
    public CorpController(CorpRepository repository) {
        this.corpRepository = repository;
    }

    @GetMapping("/")
    public ResponseEntity<Corp> getCorpByCnpj(
        @RequestParam(name = "name", required = false) String name,
        @RequestParam(name = "cnpj", required = false) String cnpj
    ) {
        System.out.println("corpCnpj " + corpCnpj);

        if(name!=null && !name.isEmpty()) {
            Corp corp = corpRepository.findByCorpName(corpName);
        } else if(name!=null && !name.isEmpty()) {
            Corp corp = corpRepository.findByCorpCnpj(corpCnpj);
        }

        return ResponseEntity.ok(corp);
    }
}

I'd suggest you to keep repository integration in service layer only. Controller layer should invoke service, and then service will call repository.

Upvotes: 0

Hussam Abd ElAziz
Hussam Abd ElAziz

Reputation: 49

What you are trying to do is to define different implementations for the same endpoint based on a query string.

If you want to do so you have to respect the fact that inside the rest controller it's only allowed to have one method to handle a specific path (although you can add different query string parameters).

So let's break down what you can do to satisfy your requirements propeply:

  • As we discussed above keep only one method on your controller which will be responsible for receivoing the request and return a response.

  • The logic of handling the request shouldn't be located inside the controller. Instead create a new Service and move the implementation from the Controller to be inside the service.

  • Create a public method inside the Service that you have created to receive the request and based on the query params route it to another private method that responsible for handling this specific parameter.

  • The public method should get the value and return it back to the Controller to return the response.

Reformat your code to be similar to:

@RestController
@RequestMapping("/api/corp")
public class CorpController {

    private final CorpService corpService;

    @Autowired
    public CorpController(CorpService corpService) {
        this.corpService = corpService;
    }

    @GetMapping
    public ResponseEntity<?> getCorp(
            @RequestParam(name = "id", required = false) String id,
            @RequestParam(name = "name", required = false) String name,
            @RequestParam(name = "cnpj", required = false) String cnpj) {

        return corpService.getCorp(id, name, cnpj);
    }
}

Your service should be similar to:

@Service
public class CorpService {

   // Method to fetch Corp by id, name, or cnpj
    public ResponseEntity<?> getCorp(String id, String name, String cnpj) {
        if (id != null) {
            // Fetch by ID
            try {
                Long corpId = Long.parseLong(id);
                Optional<Corp> corp = corpRepository.findById(corpId);
                return corp.map(ResponseEntity::ok)
                        .orElseGet(() -> ResponseEntity.notFound().build());
            } catch (NumberFormatException e) {
                return ResponseEntity.badRequest().body("Invalid ID format");
            }
        } else if (name != null) {
            // Fetch by name
            Corp corp = corpRepository.findByCorpName(name);
            return corp != null ? ResponseEntity.ok(corp) : ResponseEntity.notFound().build();
        } else if (cnpj != null) {
            // Fetch by CNPJ
            Corp corp = corpRepository.findByCorpCnpj(cnpj);
            return corp != null ? ResponseEntity.ok(corp) : ResponseEntity.notFound().build();
        }
        return ResponseEntity.badRequest().body("Missing required query parameter: id, name, or cnpj");
    }
}

Upvotes: 0

Related Questions