Skip to content

Commit

Permalink
Add controller for ai endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Zorin95670 authored and Aboubakar committed Aug 27, 2024
1 parent 936c843 commit 85b55a7
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.ditrit.letomodelizerapi.controller.CurrentUserController;
import com.ditrit.letomodelizerapi.controller.GroupController;
import com.ditrit.letomodelizerapi.controller.HomeController;
import com.ditrit.letomodelizerapi.controller.AIController;
import com.ditrit.letomodelizerapi.controller.LibraryController;
import com.ditrit.letomodelizerapi.controller.PermissionController;
import com.ditrit.letomodelizerapi.controller.RoleController;
Expand All @@ -13,7 +14,10 @@
import com.ditrit.letomodelizerapi.controller.handler.ConstraintViolationExceptionHandler;
import com.ditrit.letomodelizerapi.controller.handler.DataIntegrityViolationExceptionHandler;
import com.ditrit.letomodelizerapi.controller.handler.IllegalArgumentExceptionHandler;
import org.apache.commons.lang.StringUtils;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
Expand All @@ -24,8 +28,10 @@ public class JerseyConfig extends ResourceConfig {

/**
* Default constructor to initialize registered endpoints and filters.
* @param aiHost the host value for ai request, injected from application properties.
*/
public JerseyConfig() {
@Autowired
public JerseyConfig(@Value("${ai.host}") final String aiHost) {
// Filter
// Controller
register(UserController.class);
Expand All @@ -38,6 +44,10 @@ public JerseyConfig() {
register(CsrfController.class);
register(PermissionController.class);

if (StringUtils.isNotBlank(aiHost)) {
register(AIController.class);
}

// Exception handler
register(ApiExceptionHandler.class);
register(ConstraintViolationExceptionHandler.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.ditrit.letomodelizerapi.controller;

import com.ditrit.letomodelizerapi.model.ai.AIRequestRecord;
import com.ditrit.letomodelizerapi.persistence.model.User;
import com.ditrit.letomodelizerapi.service.AIService;
import com.ditrit.letomodelizerapi.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;

/**
* Controller to manage ai endpoint.
*/
@Path("/ai")
@Produces(MediaType.APPLICATION_JSON)
@Controller
@Slf4j
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class AIController {

/**
* Service to manage user.
*/
private UserService userService;

/**
* Service to manage ai request.
*/
private AIService aiService;

/**
* Handles a POST request to initiate an interaction with an Artificial Intelligence (AI) based on the provided
* request details.
* This endpoint accepts an AI request record, which includes the parameters necessary for the AI interaction.
* The method retrieves the user from the session, logs the request details, and forwards the request to the AI
* service. It then constructs and returns a response containing the AI's output.
*
* <p>The method uses the AI service to process the request by the user, generating a JSON response that is returned
* to the client.
* This process allows for dynamic interactions with the AI, facilitating use cases such as querying for
* information, executing commands, or initiating workflows within the application.
*
* @param request the HttpServletRequest, used to access the user's session.
* @param aiRequestRecord the request details for the AI, validated to ensure it meets the expected format.
* @return a Response object containing the AI's response in JSON format, with a status of OK (200).
*/

@POST
public Response requestAI(final @Context HttpServletRequest request,
final @Valid AIRequestRecord aiRequestRecord) throws InterruptedException {
HttpSession session = request.getSession();
User user = userService.getFromSession(session);

log.info("[{}] Received POST request to request AI with {}", user.getLogin(), aiRequestRecord);

String json = aiService.sendRequest(aiRequestRecord);

return Response.status(HttpStatus.OK.value())
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
.entity(json)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ void testConstructorShouldNotThrowException() {
Exception exception = null;

try {
new JerseyConfig();
new JerseyConfig("");
} catch (Exception e) {
exception = e;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.ditrit.letomodelizerapi.controller;

import com.ditrit.letomodelizerapi.helper.MockHelper;
import com.ditrit.letomodelizerapi.model.ai.AIRequestRecord;
import com.ditrit.letomodelizerapi.persistence.model.AccessControl;
import com.ditrit.letomodelizerapi.persistence.model.User;
import com.ditrit.letomodelizerapi.service.AIService;
import com.ditrit.letomodelizerapi.service.AIServiceImpl;
import com.ditrit.letomodelizerapi.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;

import static org.junit.jupiter.api.Assertions.*;

@Tag("unit")
@ExtendWith(MockitoExtension.class)
@DisplayName("Test class: AIController")
class AIControllerTest extends MockHelper {

@Mock
UserService userService;
@Mock
AIService service;

@InjectMocks
AIController controller;

@Test
@DisplayName("Test requestAI: should return valid response.")
void testRequestAI() throws InterruptedException {
User user = new User();
user.setLogin("login");
AIRequestRecord record = new AIRequestRecord("@ditrit/kubernator-plugin", "diagram", "I want a sample of kubernetes code");

Mockito
.when(userService.getFromSession(Mockito.any()))
.thenReturn(user);
HttpSession session = Mockito.mock(HttpSession.class);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito
.when(request.getSession())
.thenReturn(session);

Mockito.when(this.service.sendRequest(record)).thenReturn("OK");
final Response response = this.controller.requestAI(request, record);

assertNotNull(response);
assertEquals(HttpStatus.OK.value(), response.getStatus());
assertNotNull(response.getEntity());
}

}

0 comments on commit 85b55a7

Please sign in to comment.