How to implement a FIFO queue in a multi-threaded environment - java

I am trying to implement a queue for a class that fetches OpenGraph data for a url. The idea is that the OpenGraphIO service only allows for one request at a time if the request requires their "proxy" service. To eliminate the "simultaneous proxy request" errors from the service, I would like to implement a request queue inside a service class called OpenGraphFetcherImpl. However, I can't figure out how to implement the actual queue itself inside the fetch() method. Obviously the fetch() method can be called in a multi-threaded environment.
My class shell is below:
public class OpenGraphFetcherImpl implements OpenGraphFetcher {
private static final String[] domainsThatRequireProxy = {"instagram.com","facebook.com"};
private static final LinkedList<URL> proxyQueue = new LinkedList<>();
private final String api_key;
public OpenGraphFetcherImpl(String api_key) {
this.api_key = api_key;
}
/**
* Fetch OpenGraph information for a url. If the url is invalid or no data is returned, the OpenGraph
* object will be "empty" (non-null)
*
* Only one "proxy" request can be made at a time. Should a proxy be needed, the request will be queued
* and returned once previous requests have been completed.
*
* #param url end point to fetch OpenGraph data
* #return OpenGraph object
*/
#Override
#Nonnull
public OpenGraph fetch(URL url) {
if (useProxy(url)) {
// Clearly this code doesn't work, but logic should be to add the request to the queue and then make requests in FIFO order
proxyQueue.add(url);
return OpenGraphIO.fetchOpenGraphInfo(api_key, proxyQueue.poll(), true);
} else {
return OpenGraphIO.fetchOpenGraphInfo(api_key, url, false);
}
}
/**
* #param url url to test
* #return true if the host of the url matches any domains that require use of a proxy
*/
private boolean useProxy(URL url) {
return Arrays.stream(domainsThatRequireProxy).parallel().anyMatch(url.getHost()::contains);
}
}

Based on your description, you'd want to limit synchronous calls to fetch() when useProxy is true. Then, you can use an object to synchronize that case only:
public class OpenGraphFetcherImpl implements OpenGraphFetcher {
private static final Object fetchLock=new Object();
public OpenGraph fetch(URL url) {
if (useProxy(url)) {
synchronized(fetchLock) {
return OpenGraphIO.fetchOpenGraphInfo(api_key, url, true);
}
} else {
return OpenGraphIO.fetchOpenGraphInfo(api_key, url, false);
}
}
...

Related

Decorator pattern to simulate multil-layer service layer

The code examples are in PHP but the question is language agnostic.
Situation
I'm trying to figure out the best way to separate a service layer into multiple well defined layers.
In the example below I'm uploading a base64 encoded user avatar and showing how it would go through the layers. I'm using the decorator pattern to simulate the layers.
Important:
The data passed into each layer is usually changed in some way before it is passed into the next layer which is exactly what I'm looking for. The one thing I don't like about this is that in order to update an avatar you must first talk to the ValidatedProfile object instead of say a Profile object. Something about it seems weird but I could always have a Profile object which delegates calls to the ValidatedProfile.
The Layers
Validation:
This is where you validate the data. As in the example below it is where you check the format of the $avatar string and ensure it is a valid image resource. During the validation process entity objects and resources are often created which are then passed to the next layer.
Verification:
Perform checks such as verifying if a supplied ID is real. As in the example below this is where I check if the supplied user ID is actually the real ID of a user.
Commander:
Where the action to be performed happens. By the time this layer is reached the data is thought to be fully validated and verified and no further checks need to be done on it. The commander delegates the action to other services(usually entity services) and can also call other services do more actions.
Entity:
This layer works with actions to be performed on an entity and/or its relations.
ValidatedProfile
class ValidatedProfile
{
private $verifiedProfile;
/**
* #param string $avatar Example: data:image/png;base64,AAAFBfj42Pj4
*/
public function updateAvatar($userId, $avatar)
{
$pattern = '/^data:image\/(png|jpeg|gif);base64,([a-zA-Z0-9=\+\/]+)$/';
if (!preg_match($pattern, $avatar, $matches)) {
// error
}
$type = $matches[1]; // Type of image
$data = $matches[2]; // Base64 encoded image data
$image = imagecreatefromstring(base64_decode($data));
// Check if the image is valid etc...
// Everything went okay
$this->verifiedProfile->updateAvatar($userId, $image);
}
}
VerifiedProfile
class VerifiedProfile
{
private $profileCommander;
public function updateAvatar($userId, $image)
{
$user = // get user from persistence
if ($user === null) {
// error
}
// User does exist
$this->profileCommander->updateAvatar($user, $image);
}
}
ProfileCommander
class ProfileCommander
{
private $userService;
public function updateAvatar($user, $image)
{
$this->userService->updateAvatar($user, $image);
// If any processes need to be run after an avatar is updated
// you can invoke them here.
}
UserService
class UserService
{
private $persistence;
public function updateAvatar($user, $image)
{
$fileName = // generate file name
// Save the image to disk.
$user->setAvatar($fileName);
$this->persistence->persist($user);
$this->persistence->flush($user);
}
}
You could then have a Profile class like the following:
class Profile
{
private $validatedProfile;
public function updateAvatar($userId, $avatar)
{
return $this->validatedProfile->updateAvatar($userId, $avatar);
}
}
That way you just talk to an instance of Profile rather than ValidatedProfile which makes more sense I think.
Are there better and more widely accepted ways to achieve what I'm trying to do here?
I think you have too many layers. Two major objects should be enough for an operation like this. You need to validate the avatar input and persist it somehow.
Since you need to validate the user id and it is tied to persistence somehow, you can delegate that to the UserService object.
interface UserService {
/**
* #param string $userId
* #param resource $imageResource
*/
public function updateAvatar($userId, $imageResource);
/**
* #param string $userId
* #return bool
*/
public function isValidId($userId);
}
This checking for a valid user id should be a part of request validation. I would not make it a separate step like verification. So UserAvatarInput can handle that (validation implementation is just an example), and a little wrapper method to persist it all.
class UserAvatarInput {
/**
* #var UserService
*/
private $userService;
/**
* #var string
*/
private $userId;
/**
* #var resource
*/
private $imageResource;
public function __construct(array $data, UserService $service) {
$this->userService = $service; //we need it for save method
$errorMessages = [];
if (!array_key_exists('image', $data)) {
$errorMessages['image'] = 'Mandatory field.';
} else {
//validate and create image and set error if not good
$this->imageResource = imagecreatefromstring($base64);
}
if (!array_key_exists('userId', $data)) {
$errorMessages['userId'] = 'Mandatory field.';
} else {
if ($this->userService->isValidId($data['userId'])) {
$this->userId = $data['userId'];
} else {
$errorMessages['userId'] = 'Invalid user id.';
}
}
if (!empty($errorMessages)) {
throw new InputException('Input Error', 0, null, $errorMessages);
}
}
public function save() {
$this->userService->updateAvatar($this->userId, $this->imageResource);
}
}
I used an exception object to pass validation messages around.
class InputException extends Exception {
private $inputErrors;
public function __construct($message, $code, $previous, $inputErrors) {
parent::__construct($message, $code, $previous);
$this->inputErrors = $inputErrors;
}
public function getErrors() {
return $this->inputErrors;
}
}
This is how a client would use it, for example:
class UserCtrl {
public function postAvatar() {
try {
$input = new AvatarInput($this->requestData(), new DbUserService());
$input->save();
} catch (InputException $exc) {
return new JsonResponse($exc->getErrors(), 403);
}
}
}

variable / constructor in an interface

I was going through the picasso source code and came across this chunk in lines 80-94:
public interface RequestTransformer {
/**
* Transform a request before it is submitted to be processed.
*
* #return The original request or a new request to replace it. Must not be null.
*/
Request transformRequest(Request request);
/** A {#link RequestTransformer} which returns the original request. */
RequestTransformer IDENTITY = new RequestTransformer() {
#Override public Request transformRequest(Request request) {
return request;
}
};
}
From my understanding, it's somewhat declaring a variable in the interface with a static constructor. Can someone explain what is that code supposed to be doing? I read through a similar post regarding constructors in interfaces (Constructor in an Interface?) but I still don't see why this case does not apply there.
Thanks
This actually is not a variable. This is constant with anonymous implementation. Within interface it is compiled to:
public interface RequestTransformer {
Request transformRequest(Request request);
public static final RequestTransformer IDENTITY = new RequestTransformer() {
#Override
public Request transformRequest(Request request) {
return request;
}
};
}
And this is a bad practice (to have implementation within interface) :)

When is JMXBean initialised

IMEI I am new to MXbeans. I want to understand when is the MXBean actually initialized, in the application which I am supporting we have a notification system and I can not see my MXBean in JConsole until there is some notification arriving. Here is a code of my MXBean.
package mecomaany.instrumentation;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import BulkCMIRP_MxBean;
import SoapIRPLogger;
/**
* This dynamic MBean exposes a method to return the 10 latest Basic CM
* operations.
*
* #author eshtrom
*
*/
public class BasicCMIRP_MxBean implements DynamicMBean{
private static final String CLASS_NAME = BasicCMIRP_MxBean.class.getCanonicalName();
private static final String MX_BEAN_NAME = BasicCMIRP_MxBean.class.getCanonicalName() + ":Type=BasicCMIRP_MxBean";
private static final String BEAN_DESCRIPTION = "Instrumentation bean for SOAP Basic CM IRP.";
private static final int NUM_OPERATIONS_TO_RECORD = 10;
private final ArrayList<String> basicCMOperations = new ArrayList<String>();
/**
* Register the bean. This is a best effort attempt. If registration fails
* we'll report it but nothing more.
*/
public BasicCMIRP_MxBean() {
registerMxBean();
}
/**
* Attempt to unregister and clean up the MX beans.
*/
public void destroy() {
basicCMOperations.clear();
unregisterMxBean();
}
/**
* This method returns a description of this bean to the JMX interface. The
* description is just a list of names of the currently stored attributes.
*/
public synchronized MBeanInfo getMBeanInfo() {
final MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[0];
final MBeanOperationInfo[] operations = { new MBeanOperationInfo("getBasicCMInstrumentation", "Get instrumentation Basic CM IRP bean.", null, "String[]",
MBeanOperationInfo.INFO) };
return new MBeanInfo(this.getClass().getName(), BEAN_DESCRIPTION, attributes, null, operations, null);
}
/**
* Callback to execute methods exposed by this dynamic MBean.
*/
public Object invoke(final String actionName, final Object[] params, final String[] signature) throws MBeanException, ReflectionException {
SoapIRPLogger.enter(CLASS_NAME, "invoke");
if (actionName != null) {
if (actionName.equals("getBulkCMInstrumentation")) {
return getBasicCMInstrumentation();
}
}
SoapIRPLogger.exit(CLASS_NAME, "invoke");
throw new ReflectionException(new NoSuchMethodException(actionName));
}
/**
* Construct a human readable very of the last 10 operations and return it.
*
* #return string array as an object.
*/
private Object getBasicCMInstrumentation() {
SoapIRPLogger.enter(CLASS_NAME, "getBasicCMInstrumentation");
String[] result = new String[basicCMOperations.size()];
int index = 0;
for (String operation : basicCMOperations) {
result[index] = operation;
index++;
}
SoapIRPLogger.exit(CLASS_NAME, "getBasicCMInstrumentation");
return result;
}
/**
* No attributes are writable so this method will throw an exception.
*/
public void setAttribute(final Attribute arg0) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
throw new AttributeNotFoundException("All attributes on this bean are read only.");
}
/**
* No attributes are writable so this method will return an empty list.
*/
public AttributeList setAttributes(final AttributeList arg0) {
return new AttributeList();
}
public Object getAttribute(final String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
throw new AttributeNotFoundException("No attributes are defined on this MX bean.");
}
/**
* No attributes are readable so this method will return an empty list.
*/
public AttributeList getAttributes(final String[] attributes) {
return new AttributeList();
}
/**
* Add or update and instrumentation attribute. A null attribute name will
* be ignored.
*
* #param name
* #param value
*/
public void updateInstrumentationAttibute(final String name, final String value) {
// The only attribute that this bean supports is Bulk CM operations.
if (name.compareTo("BasicCM_Operations") == 0) {
basicCMOperations.add(value);
// We'll only record a maximum of 10 operations. If we exceed the
// max, remove the oldest.
if (basicCMOperations.size() > NUM_OPERATIONS_TO_RECORD) {
basicCMOperations.remove(0);
}
}
}
public ObjectName getBeanName() throws MalformedObjectNameException, NullPointerException {
// Construct the ObjectName for the MBean we will register
return new ObjectName(MX_BEAN_NAME);
}
/**
* Register the bean.
*/
protected void registerMxBean() {
try {
ManagementFactory.getPlatformMBeanServer().registerMBean(this, this.getBeanName());
} catch (Exception e) {
SoapIRPLogger.exception(CLASS_NAME, "Constructor", "Failed to register BulkCMIRP_MxBean management beans.", e);
}
}
protected void unregisterMxBean() {
try {
ManagementFactory.getPlatformMBeanServer().unregisterMBean(this.getBeanName());
} catch (Exception e) {
// Suppress exceptions, we're closing down anyway.
}
}
}
Loner;
Your MXBean should be visible in JConsole as soon as you construct it, since the constructor calls registerMxBean() which registers the MBean with the platform MBeanServer.
Assuming your JConsole is already running when the MBean is registered, JConsole's view of the MBean will be dictated by the first instance of the MBeanInfo that is generated on registration. Since you coded this as a DynamicMBean, I wonder if your intent was to periodically modify the MBeanInfo, but be aware that once a JConsole connection has retrieved the MBeanInfo for a registered bean, it will not refresh it. If the MBeanInfo changes, you must closed the connection in JConsole and open it again.
Consequently, your issue may be outside the code you have supplied, or more simply put, when is the instance of BasicCMIRP_MxBean created ?
Your comment about not seeing the bean until notifications start arriving makes me wonder if you mean that:
A. You cannot see the MBean until notifications start arriving, in which case I would assume that there is some activation code that creates the instance when a [the first ?] notification arrives, or
B. What you mean is that you cannot see specific properties of the MBean until notifications start arriving.
Perhaps you could clarify the larger picture here.
Some additional observations that may be unrelated:
The MBeanInfo you are generating specifies that the one and only operation is called getBasicCMInstrumentation (basic), but your invoke handler only attempts to decode an operation called getBulkCMInstrumentation (bulk). JConsole is supplied the MBeanInfo in order to render the operations so the console believes that the operation is called basic but the MBean will only respond to a request called bulk.
The signature for method getBasicCMInstrumentation returns an Object but what the code really returns is a String[]. This may work because your MBeanInfo specifies that a String[] is returned, but for consistency and clarity I would change the method signature.
//Nicholas

java.lang.AssertionError: Unexpected method call convertMessagesAsAppropriate(com.Response#1bb35b)

Need help is deciding what approach needs to be taken to test below piece of code
I have one method called
private messageDAOInf messageDAO;
public Response verifyUser(Request request) {
Response response = null;
if (someCondition) {
/* -----------Some processing here---------- */
} else {
response = constructResponse(errorCode, errorDesc);
}
// Do more processing with messages from response
response = messageDAOInf
.convertMessagesAsAppropriate(response);
return response;
}
My EasyMock code is here
/** The message dao inf. */
private MessageDAOInf messageDAOInf;
private VerifyUserService verifyUserServiceI;
#Before
public void setUp() throws Exception {
messageDAOInf = EasyMock.createMock(MessageDAOInf.class);
verifyUserService = new VerifyUserService();
verifyUserService.setMessageDAOInf(messageDAOInf);
}
#Test
public void testErrorResponse() {
Request request = loadRequest();
Response response = constructErrorResponse();
EasyMock.expect(messageDAOInf.convertMessagesAsAppropriate(
response)).andReturn(response);
EasyMock.replay(messageDAOInf);
Response response2 = verifyUserService.verifyUser(request);
assertFailedResponse(response2);
}
The issue is from line
response = constructResponse(errorCode, errorDesc);
it constructs error response in verifyUser method and passes it to
messageDAOInf.convertMessagesAsAppropriate()
But with easy mock it passes some other instance (mocked one) and hence failes with error
java.lang.AssertionError:
Unexpected method call convertMessagesAsAppropriate(***Response#1bb35b***):
convertMessagesAsAppropriate(***Response#1b5d2b2***): expected: 1, actual: 0
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:29)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:56)
Let me know what approach I should take.
Thank you.
Your initial code expects that convertMessagesAsAppropriate will be called with the exact instance of Response that you created in the test: obviously it will not do that.
The correction you've made is essentially the same as using the built-in EasyMock.anyObject() method which will allow any Response instance. If that's all you want to check in your unit test, that's fine. Alternatively you can add extra logic into your ArgumentMatcher to prove that the Response that is passed as an argument really is an ErrorResponse, or Capture the response and examine it in your test. This all depends on your level of testing :-)
I have found out way of doing it.
You need to implement interface org.easymock.IArgumentMatcher
public class ObjectEquals implements IArgumentMatcher {
/** The expected. */
private Object expected;
/**
* Instantiates a new criterion equals.
*
* #param expected
* the expected
*/
public ObjectEquals(final Object expected) {
this.expected = expected;
}
/* (non-Javadoc)
* #see org.easymock.IArgumentMatcher#matches(java.lang.Object)
*/
public boolean matches(final Object actual) {
return expected.getClass().equals(actual.getClass());
}
/* (non-Javadoc)
* #see org.easymock.IArgumentMatcher#appendTo(java.lang.StringBuffer)
*/
public void appendTo(final StringBuffer buffer) {
buffer.append("buffer(");
}
}
and in your test class add method
/*
* Eq criterion.
*
* #param criterion the criterion
*
* #return the criterion
*/
public static <T> T eqCriterion(final Class<T> className, Object object) {
EasyMock.reportMatcher(new ObjectEquals(object));
return null;
}
Now while passing to easymock use method eqCriterion at line
EasyMock.expect(messageDAOInf.convertMessagesAsAppropriate(
response)).andReturn(response);
In short replace above line with
EasyMock.expect(messageDAOInf.convertMessagesAsAppropriate(
eqCriterion(Response.class, response))).andReturn(response);
This way it will use this mocked response instance instead of one generated by actual code.

Mocking inside a Java class

So I have this GWT code that handles RPC requests maintain states(ready, waiting, error etc).
And I would like to check if the class change its states correctly after each call, set response variables etc.
Now how should I proceed to test that without making actual requests to the server(that could run into errors in the server it self).
I think I could mock the request callback class somehow but it is invisible to the test.
I'm lost, help!
Sample of the code below(I'll post the whole thing later in case anyone wants).
public class RPCHandler
{
public RPCHandler(String method,String[] argumentsName,
String[][] argumentsValues)
{
this.method = method;
this.argumentsName = argumentsName;
this.argumentsValues = argumentsValues;
}
/**
* Method that creates a RPC request using JSON in a POST
*
*/
public void rpcRequest(){
if(currentState == HandlerState.WAITING_RESPONSE)return;
currentState = HandlerState.WAITING_RESPONSE;
// Append watch list stock symbols to query URL.
url = URL.encode(url);
url += "action=";
url += method;
// Send request to server and catch any errors.
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
String requestData = parseToJSON(argumentsName, argumentsValues);
try{
Request request = builder.sendRequest(requestData, new RequestCallback()
{
public void onError(Request request, Throwable exception)
{
setRPCException(new Exception("Error while saving. Action="+method));
setCurrentState(HandlerState.ON_ERROR);
}
//Few other error, response received hander methods after this point.
}
}
It looks like you're trying to mock out the actual transport so you should build a mock of the RequestBuilder class. In JMockit, you could write:
public class MockRequestBuilder
{
public void $init( int method, String url)
{
/* check values and/or store for later */
}
public Request sendRequest( String data, RequestCallback callback )
{
/* check values and/or store for later */
}
}
You'll need to fill in the details of the what you want the mock to do. Also, you can isolate the callback testing if you moved the callback to a named class instance inside of your outer class:
public class MyGWTClass
{
protected static class RpcCallback extends RequestCallback
{
public void onError(...) { ... }
}
}
By moving the callback object into a class and using a factory method, you can create tests that only check the callback.

Categories