Friday, June 14, 2024

How authenticationProvide interact with UserDetailService?

 

The AuthenticationProvider is the component that implements the authentication logic and uses the UserDetailsService to load details about the user. To find the user by username, it calls the loadUserByUsername(String username) method.

Thursday, June 13, 2024

Relationship between UserDetailService, UserDetails and UserDetails manager

 

The UserDetailsService returns the details of a user, finding the user by its name. The UserDetails contract describes the user. A user has one or more authorities, represented by the GrantedAuthority interface. To add operations such as create, delete, or change password to the user, the UserDetailsManager contract extends UserDetailsService to add operations.

Tuesday, February 13, 2024

Command design pattern

 When to implement ?

Suppose we have a situation ,

There are multiple action to execute based on a single value or criteria. There are several solution to do . We can use if.. else if ladder or switch case to do that  and define the action in each separate method . But if the action feature grow then we need to refactor and transfer the defined action in class . It will we time consuming . So in that situation we can implement Command design pattern like below.

 interface CampaignContactCommand {
        void execute();
    }
    
    class PauseContactCommand implements CampaignContactCommand {

        private ContactHelperNode node;

        public PauseContactCommand(ContactHelperNode node) {
            this.node = node;
        }

        @Override
        public void execute() {
            ContactPauseHelper helper = new ContactPauseHelper(node);
            helper.pauseContact();
            helper.release();
        }
    }
    
    class ResumeContactCommand implements CampaignContactCommand{

        private ContactHelperNode node;
        
        public ResumeContactCommand(ContactHelperNode node) {
            this.node = node;
        }
        
        @Override
        public void execute() {
            ContactResumeHelper helper = new ContactResumeHelper(node);
            helper.resumeContact();
            helper.release();
        }
    }
    
    class UnsubscribeContactCommand implements CampaignContactCommand {

        private ContactHelperNode node;

        public UnsubscribeContactCommand(ContactHelperNode node) {
            this.node = node;
        }

        @Override
        public void execute() {
            ContactUnSubHelper helper = new ContactUnSubHelper(node);
            helper.unSubContact();
            helper.release();
        }
    }
    
    class CampaignContactCommandFactory {
        private ContactHelperNode node;

        public CampaignContactCommandFactory(ContactHelperNode node) {
            this.node = node;
        }

        public CampaignContactCommand createCommand() {

            switch (node.getRequest().getRequestType()) {

            case PAUSE:
                return new PauseContactCommand(node);
            case RESUME:
                return new ResumeContactCommand(node);
            case UNSUB:
                return new UnsubscribeContactCommand(node);
            default:
                return null;
            }
        }
    }

Monday, December 25, 2023

Upload file to S3 api

 @Path("files")
@Log4j2
@Component
public class FileUploadController implements ConfigInterface{

    @Context
    private SecurityContext securityContext;
    
    @Inject
    private FileUploadAPIValidator paramValidator;
    
    @Path("/config")
    public Resource getConfigResource() {
        return Resource.from(ConfigController.class);
    }
    
    /**
     * @author lokman 20/11/2022
     *
     */
    @POST
    @Secured
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_JSON)
    @RequestTracingFilter
    public Response uploadMultipleFile(@FormDataParam("files") List<FormDataBodyPart> files, @FormDataParam("files") List<FormDataContentDisposition> fileDetails) {
        
        log.info("file size :"+ fileDetails.size());
        
        JSONObject response = new JSONObject();
        
        BasicCacheUserPrincipal userPrincipal = (BasicCacheUserPrincipal) securityContext.getUserPrincipal();

        if (userPrincipal == null || userPrincipal.getUser() == null) {
            response.put("responseCode", HttpStatus.SC_UNAUTHORIZED);
            response.put("message", "Unauthorized");
            response.put("success", Boolean.FALSE);

            return Response.status(HttpStatus.SC_UNAUTHORIZED).entity(response.toString()).build();
        }
        
        if (fileDetails.size() == 1 && StringUtil.isBlank(fileDetails.get(0).getFileName())) {

            response.put("responseCode", HttpStatus.SC_OK);
            response.put("message", "No file selected.");
            response.put("success", Boolean.FALSE);

            return Response.status(HttpStatus.SC_UNAUTHORIZED).entity(response.toString()).build();
        }
        
        if (fileDetails.size() > DefaultConfig.MAX_FILE_SIZE) {
            response.put("responseCode", HttpStatus.SC_OK);
            response.put("message", "Maximum 10 files allowed.");
            response.put("success", Boolean.FALSE);

            return Response.status(HttpStatus.SC_UNAUTHORIZED).entity(response.toString()).build();
        }
        
        List<String> fileUrls = new ArrayList<>();
        
        for (int j = 0; j < files.size(); j++) {
            
            FormDataBodyPart formDataBodyPartFile = files.get(j);
            ContentDisposition contentDispositionHeader = formDataBodyPartFile.getContentDisposition();
            InputStream fileInputStream = formDataBodyPartFile.getValueAs(InputStream.class);
            FormDataContentDisposition fileDetail = (FormDataContentDisposition) contentDispositionHeader;
            
            FileUploadAPIValidationResponse verifyResponse = paramValidator.verifyFiles(fileInputStream, fileDetail);
            
            File tempFile = null;
            if(verifyResponse.isValid()) {
                String fileName = userPrincipal.getUser().getId() + "_" + "form" + "_" + System.currentTimeMillis() + "_" + fileDetail.getFileName();
                
                log.info("fileName :"+ fileName);
                
                tempFile = new File(fileName);
                
                FileOutputStream fileOutputStream = writeToFile(verifyResponse.getInputStream(), tempFile);
                log.debug("file length : "+ tempFile.length());
                
                if ((tempFile.length() / CommonUtils.ONE_MEGABYTE_IN_BYTES) > DefaultConfig.MAX_FILE_SIZE) {
                    removeExistingFile(tempFile);
                    fileOutputStream = null;
                    continue;
                }
                
                if (fileOutputStream != null) {
                    String fileUrl = uploadFileToS3(tempFile);
                    if (StringUtil.isNotBlank(fileUrl)) {
                        log.info("fileUrl :" + fileUrl);
                        
                        fileUrls.add(fileUrl);
                    }
                }
            }
            if(tempFile != null) {
                removeExistingFile(tempFile);
            }
        }
        
        log.info("fileUrls :"+ fileUrls.size());
        
        if(fileUrls.isEmpty()) {
            response.put("responseCode", HttpStatus.SC_OK);
            response.put("message", "File upload failed.");
            response.put("success", Boolean.FALSE);
            return Response.status(HttpStatus.SC_OK).entity(response.toString()).build();
        }
        
        response.put("responseCode", HttpStatus.SC_OK);
        response.put("message", "File uploaded successfully.");
        response.put("success", Boolean.TRUE);
        response.put("urls", fileUrls);
        return Response.status(HttpStatus.SC_OK).entity(response.toString()).build();
    }
    
    /**
     * @author lokman 19/11/2022
     *
     */
    private FileOutputStream writeToFile(InputStream inputStream, File tempFile) {
        
        byte[] data = new byte[1024];

        FileOutputStream fileOutputStream = null;
        int read = 0;
        try {
            fileOutputStream = new FileOutputStream(tempFile);
            while ((read = inputStream.read(data)) != -1) {
                fileOutputStream.write(data, 0, read);
            }
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileOutputStream;
    }
    
    /**
     * @author lokman 19/11/2022
     * @param file
     */
    private String uploadFileToS3(File file) {
        try {
            String folder = S3Config.AWS3_SECTION_USER+"/";
            log.debug("Folder : "+folder);
            AWS3ApiResponse response = AWS3APIFactory.getAWS3API().uploadPublicFile(S3Config.AWS3_BUCKET_NAME, folder, file);
            log.info(" s3 upload Success : "+response.isSuccess());
            if(response.isSuccess()) {
                log.info("FileUrl : "+response.getFileUrl());
                return response.getFileUrl();
            }
        } catch (Exception e) {
            log.error("Exception : "+ e);
        }
        return null;
    }
    
    /**
     * @author lokman 19/11/2022
     * @param file
     */
    private void removeExistingFile(File file) {
        try {
            if (file.exists()) {
                boolean fileRemoved = file.delete();
                log.debug("fileRemoved : " + fileRemoved);
            }
        } catch (Exception e) {
            log.error("errorMessage ", e);
        }
    }
}

Wednesday, December 13, 2023

Bulk data insert using prepared statement

     public Optional<List<UUID>> addInBatch(List<ApiActionLogs> apiActionLogs) {
        
        if (apiActionLogs == null || apiActionLogs.isEmpty()) {
            return Optional.ofNullable(Collections.emptyList());
        }
        List<UUID> insertedUUIDList = new ArrayList<>();
        ByteArrayToUUIDConverter byteArrayToUUIDConverter = new ByteArrayToUUIDConverter();
        try (Connection connection = ConnectionUtil.getWriteConnection()) {
            connection.setAutoCommit(false);
            String sql = String.format(
                    "INSERT INTO %s (uuid, agency_id, user_id, `action`, api_bulk_action_queues_uuid, message_log, "
                    + "status, response_code, request_data, created_at, updated_at) "
                    + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "api_action_logs ");
            
            try (PreparedStatement statement = connection.prepareStatement(sql,                                  Statement.RETURN_GENERATED_KEYS)) {
                int counter = 0;
                int batchSize = 100;
                List<UUID> batchRequests = new ArrayList<>();
                
                for (ApiActionLogs apiActionLog : apiActionLogs) {
                    if (apiActionLog == null
                            || apiActionLog.getAgencyId() == null
                            || apiActionLog.getUserId() == null
                            || apiActionLog.getApiBulkActionQueuesUuid() == null) {
                        continue;
                    }
                    statement.clearParameters();
                    apiActionLog.setUuid(UUID.randomUUID());
                    
                    statement.setBytes(1, byteArrayToUUIDConverter.to(apiActionLog.getUuid()));
                    statement.setString(2, apiActionLog.getAgencyId().toString());
                    statement.setString(3, apiActionLog.getUserId().toString());
                    statement.setString(4, apiActionLog.getAction() == null ? null : apiActionLog.getAction().name());
                    statement.setBytes(5,  byteArrayToUUIDConverter.to(apiActionLog.getApiBulkActionQueuesUuid()));
                    statement.setString(6, apiActionLog.getMessageLog());
                    statement.setString(7, apiActionLog.getStatus() == null ? null : apiActionLog.getStatus().name());
                    statement.setString(8, apiActionLog.getResponseCode());
                    statement.setString(9, apiActionLog.getRequestData() == null ? null : apiActionLog.getRequestData().toString());
                    statement.setTimestamp(10, Timestamp.valueOf(LocalDateTime.now()));
                    statement.setTimestamp(11, Timestamp.valueOf(LocalDateTime.now()));
                    
                    statement.addBatch();
                    
                    batchRequests.add(apiActionLog.getUuid());
                    
                    if ((counter + 1) % batchSize == 0 || (counter + 1) == apiActionLogs.size()) {
                        try {
                            statement.executeBatch(); // Execute Batch Operations
                            insertedUUIDList.addAll(batchRequests);
                            batchRequests.clear();
                        } catch (Exception e) {
                            log.error("Error :{}", e);
                            System.out.println("Error "+e);
                            if (!connection.isClosed()) {
                                connection.rollback();
                            }
                            batchRequests.clear();
                        }
                        
                        statement.clearBatch();
                    }
                    
                    counter++;
                }
            } catch (Exception e) {
                log.error("Error :{}", e);
                System.out.println("Error2 "+e);
                e.printStackTrace();
            }

            connection.commit(); // execute prepare statement
            
            if(!insertedUUIDList.isEmpty()) {
                
                return Optional.ofNullable(insertedUUIDList);
            }
            
        } catch (Exception e) {
            log.error("Error :{}", e);
            System.out.println("Error3 "+e);
            e.printStackTrace();
        }

        return Optional.ofNullable(Collections.emptyList());
    }

Testing controller

------Controller------------- @RestController @RequestMapping("/items") public class ItemController {     private final ItemServic...