Java tutorial
/* * Copyright 2015 Karl Dahlgren * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.castlemock.web.basis.service; import com.castlemock.core.basis.model.*; import com.castlemock.core.basis.model.user.domain.User; import com.castlemock.core.basis.model.validation.validator.NotNullValidator; import com.castlemock.core.basis.model.validation.validator.Validator; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Future; /** * The ServiceProcessor is responsible for processing input message and route them to the service responsible * for processing and handling the incoming message. The ServiceProcessor is also responsible for validating * both the input and output message. * @author Karl Dahlgren * @since 1.0 */ @Component public class ServiceProcessorImpl implements ServiceProcessor { @Autowired private ServiceRegistry serviceRegistry; private static final String UNKNOWN_USER = "Unknown"; private static final Logger LOGGER = Logger.getLogger(ServiceProcessorImpl.class); private static final List<Validator> VALIDATORS = new ArrayList<Validator>(); static { VALIDATORS.add(new NotNullValidator()); } /** * The process method is responsible for processing the incoming input message and * route it to the corresponding service class. * @param input The incoming input message * @param <I> Input type * @param <O> Output type * @return Returns the service result generated by the service responsible for processing the incoming input message */ @Override public <I extends Input, O extends Output> O process(final I input) { validateMessage(input); final Service<I, O> service = serviceRegistry.getService(input); if (service == null) { throw new IllegalArgumentException("Unable to find service for " + input.getClass().getSimpleName()); } final ServiceTask<I> serviceTask = new ServiceTask<I>(); serviceTask.setInput(input); serviceTask.setServiceConsumer(getLoggedInUsername()); LOGGER.debug(getLoggedInUsername() + " is requesting " + service.getClass().getSimpleName() + " to process the following input message: " + input.getClass().getSimpleName()); final ServiceResult<O> serviceResult = service.process(serviceTask); validateMessage(serviceResult.getOutput()); return serviceResult.getOutput(); } /** * Very much like the {@link ServiceProcessor#process(Input)}, the process async method is responsible for * processing the incoming input message and route it to the corresponding service class. However, the main * difference between this method and {@link ServiceProcessor#process(Input)} is that this method process * the input message asynchronously. The method will return a future object instead. The future object * contains methods to determine the state of the ongoing process, such as {@link Future#isDone()}. * @param input The incoming input message * @param <I> Input type * @param <O> Output type * @return Returns the service result generated by the service responsible for processing the incoming input message */ @Override @Async public <I extends Input, O extends Output> Future<O> processAsync(final I input) { O output = process(input); return new AsyncResult<O>(output); } /** * The method is responsible for validating the incoming or outgoing message with all the registered validators * @param message The message that will be validated * @param <M> The message type (Input or output) * @see Message * @see Input * @see Output * @see Validator */ private static <M extends Message> void validateMessage(M message) { for (Validator validator : VALIDATORS) { validator.validateMessage(message); } } /** * Get the current logged in user username * @return The username of the current logged in user * @see User */ protected String getLoggedInUsername() { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { return UNKNOWN_USER; } return authentication.getName(); } }