I have written a web-service application that has in a main class generated random value per request (for logging).
I cannot set it as a static field because next request will override it.
I also cannot pass it to the every class that I use in the main one (as an argument or with setter).
Is it possible to create some semi-static field - visible for one request but not for every other that go to the web-service ?
You can safely assume that, in the Java EE model, each single request is served by a single thread and that there is no contention by concurrent requests.
Having said that, you can employ a Singleton using a ThreadLocal, let the Servlet populate the value and have the underlying classes access the sigleton without having notion of the threads or the HTTP request context:
public class RandomValueHolder {
private static ThreadLocal<Long> randomValue;
public static Long getRandomValue() {
return randomValue.get();
}
public static void setRandomValue(Long value) {
randomValue = new ThreadLocal<Long>();
randomValue.set(value);
}
}
Why not use HttpRequest and store the value as attribute
Save the data in the request itself with Request.setAttribute() and use the corresponding Request.getAttribute() to retrieve it.
Related
I have a POST request that I would like to synchronize based on the incoming request body POJO. The request body has a variable by which I can identify if the incoming request is a duplicate or not.
My problem is that each incoming request body has a different reference.
I am generating some sort of confirmation number with the sample request body. I am getting multiple confirmation numbers for the same identifier(property inside SampleRequestBody class) which I don't want.
#PostMapping(value = "testingSync", headers = {"Content-type=application/json"})
public void testingSync(#RequestBody SampleRequestBody sampleRequestBody) {
synchronized(sampleRequestBody) {
//Do some process with the sample request body
}
}
The sample request body looks something like this
public class SampleRequestBody {
private String identifier;
public String getIdentifier(){
return this.identifier;
}
public void setIdentifier(String identifier){
this.identifier = identifier;
}
}
The synchronized block synchronizes calls that are using the same instance. As each call to your service will create a new instance of SampleRequestBody there is practically no synchronization.
You could synchronize on the identifier property of you request object by storing the strings in some kind of local cache in order to get the same string instance for the same identifier again:
// you should not actually use String.intern() here but some local cache
synchronized(sampleRequestBody.getIdentifier().intern()) {
//Do some process with the sample request body
}
The above example uses String.intern() just for the sake of simplicity. In a real live application using String.intern() should be avoided as it will create objects in memory that are not covered by the Java GC. That is: use a local cache instead.
You should additionally keep in mind that this synchronization will only work on a per JVM basis. That is, if you got two servers in a load balanced setup, this will not work as desired.
And one last thought: You should really rethink the need of synchronization here. Use it only if there is no other possibility to solve your requirements.
If you need a tool to synchronization by the value of the object which you can use in Spring Framework then I can suggest you XSync library.
All that you need is to add the XSync bean in your configuration:
#Configuration
public class Config{
#Bean
public XSync<String> xSync(){
return new XSync<>();
}
}
and now you can use it in your controller:
#Autowired
private XSync<String> xSync;
#PostMapping(value = "testingSync", headers = {"Content-type=application/json"})
public void testingSync(#RequestBody SampleRequestBody sampleRequestBody) {
xSync.execute(sampleRequestBody.getIdentifier(), () -> {
//Do some process with the sample request
});
}
Implementation of this library based on the WeakReference instead of String.intern.
Using String.intern here is a bad idea, you can get a deadlock and memory leaks.
I have a use case where I am creating multiple AWS resources, for example S3 buckets, SNS topics etc in a cloudformation stack. All of these are bare minimalistic resources i.e the S3 bucket would not have any objects in it.
I have a workflow set up where my code will pick up a random resourceType and then create the resource. Now, I am trying to build a generic class/method which would delete these created resources.
I store the resources as json fields which give me the details about the resourceType
{
"AWSService": "S3",
"AWSResourceType": "Bucket",
"ResourceAttributes" : {
"BucketName": "MyBucket"
}
}
For the cleanup, I was thinking that I have a map with key as the AWSService and the value to be a runnable which would call the appropriate serviceType to delete the resource.
But, runnables cannot take in parameters, and therefore I cannot pass in the resourceName/Arn to be deleted so that the API knows which resource to delete.
Is there a way I can store this information as a map and still pass in parameters to the method being executed?
Not sure I fully understand all of the implications of what you are doing without seeing some code, but I think this might get you going in the right direction.
You can implement the Runnable interface in a new generic class: http://leo.ugr.es/elvira/devel/Tutorial/Java/essential/threads/clock.html
So what you could do is create a generic class that implements the runnable interface, and has either a constructor that can take the variables you need, or getters/setters, etc.
Something along the lines of:
public class ResourceCleanup implements Runnable {
private String arn;
#Override
public void run() {
// do the cleanup with the arn
}
public ResourceCleanup(String arn) {
this.arn = arn;
}
// etc.
}
Or you could pass in the map instead of the String, use Java Generics, etc. as necessary. Hope this helps!
Lets say I have a Java function something like
public int getNumber(){
}
which returns some value based on it's logic. And I have a JS file something like
Tapestry.Validator.amountValidator = function(field, message) {
field.addValidator(function(value) {
if (value != null) {
// code here
}
}
});
};
Now I am asking myself is it possible in JS or JQuery to pass value from Java function to it's function(value) in JS and if so, how can it be achieved?
UPDATE: As suggested by abalos answer, Tap for myself has already done 3 out of 4 stages for it. I am providing a function that deals with server side and logic behind it.
#InjectComponent
private TextField amount;
#Inject
private FieldValidatorSource fieldValidatorSource;
public FieldValidator<?> getAmountValidator()
{
return fieldValidatorSource.createValidators(amount, "required,max=" + getBroj());
}
Now here validator is taken from a logic inside a function getBroj(), which is maximum number of what it takes. And this works like a charm on server side. Now I was thinking that what I don't have( using my logic ) is only Client side, and I can achieve it by updating current Validation class from Tapestry that will handle with this kind of request yet known to that class. And to do it I would need to call a js file with a function calling something like above in the example, but I am not quite sure how to pass value from getNumber() function to the JS function above.
You don't need Jersey or DWR or any other framework at all for invoking a method in Tapestry. You just need to ask your questions properly.
final private static String EVENT_NAME = "whateverEventNameYouWant";
#Inject
private ComponentResources resources;
#Inject
private JavaScriptSupport javaScriptSupport;
/** Method that will provide the value you want to pass to JS. */
#OnEvent(EVENT_NAME)
public JSONObject provideValue() {
JSONObject object = new JSONObject();
object.put("value", /* the value you want to pass to JS */);
// other values you may want to pass
return object;
}
void afterRender() {
// This creates an URL for the event you created. Requesting it will
// invoke any event handler methods for that event name.
Link link = resources.createEventLink(EVENT_NAME);
javaScriptSupport.addScript("var eventUrl = '%s';", link.); // the JavaScript variable name doesn't matter. You can choose any you want
}
Then, in your JavaScript, do an AJAX request using the URL in the eventUrl variable. I'll leave this part for you to figure out from the jQuery documentation. The received data is exactly the JSONObject or JSONArray you'll return in your event handler method.
I think you have some very heavy misconceptions into what types of languages Java and jQuery/Javascript are. First off, with the exception of node.js, jQuery/Javascript are used for client-side operations. Java is used for server-side operations. This means that you will need to pass a value from the server to the client.
Now, what you are asking for looks initially like it is trying to perform validation. This should not be completed only on the client-side. There are ways to get around client validation and it is best to leave information from the client in an "untrusted" state until it is validated on the server.
With all that said, to do what you are trying to do will require the use of some method for the client to communicate with the server. My favorite way to do this for simple operations is through a web service.
Here are steps to do what you require, but note that this is not the only way.
Create a web service with Jersey.
Pass the value to the web service via AJAX with either JSON or XML with a request that contains the value.
Perform your validation on the server-side with the information from the service.
Pass a response from the rest service back to the client-side AJAX call and use it for your JS/jQuery code.
Let me know if you have any questions.
So I'm writing a web service architecture which includes FunctionProvider classes which do the actual processing of requests, and a main Endpoint class which receives and delegates requests to the proper FunctionProvider.
I don't know exactly the FunctionProviders available at runtime, so I need to be able to 'register' (if that's the right word) them with my main Endpoint class, and query them to see if they match an incoming request.
public class MyFunc implements FunctionProvider{
static {
MyEndpoint.register(MyFunc);
}
public Boolean matchesRequest(Request req){...}
public void processRequest(Request req){...}
}
public class MyEndpoint{
private static ArrayList<FunctionProvider> functions = new ArrayList<FunctionProvider>();
public void register(Class clz){
functions.add(clz);
}
public void doPost(Request request){
//find the FunctionProvider in functions
//matching the request
}
}
I've really not done much reflective Java like this (and the above is likely wrong, but hopefully demonstrates my intentions).
What's the nicest way to implement this without getting hacky?
Do not let the FunctionProviders self register. Bootstrap the endpoint through some application init. call with a list of FunctionProviders. That way you can configure priority (what if two providers both claim they can process a request?). The way you set it up now you need to invoke the class somehow to trigger the static constructor, too indirect.
If detecting whether or not a FunctionProvider supports a given request is trivial consider making it part of configuration. If this is in the request map it to that FunctionProvider. This would seperate concerns a bit better. If the detection is complicated consider doing it in seperate classes from the FunctionProvider.
By configuring a delegate/function pointer you can possibly prevent from needing a FunctionProvider altogether (not sure if/how Java supports delegates).
In a GWT app I present items that can be edited by users. Loading and saving the items is perfomed by using the GWT request factory. What I now want to achive is if two users concurrently edit an item that the user that saves first wins in the fashion of optimistic concurrency control. Meaning that when the second user saves his changes the request factory backend recognizes that the version or presence of the item stored in the backend has changed since it has been transfered to the client and the request factory/backend then somehow prevents the items from being updated/saved.
I tried to implement this in the service method that is used to save the items but this will not work because request factory hands in the items just retrieved from the backend with applied user's changes meaning the versions of these items are the current versions from the backend and a comparison pointless.
Are there any hooks in the request factory processing I coud leverage to achieve the requested behaviour? Any other ideas? Or do I have to use GWT-RPC instead...
No: http://code.google.com/p/google-web-toolkit/issues/detail?id=6046
Until the proposed API is implemented (EntityLocator, in comment #1, but it's not clear to me how the version info could be reconstructed from its serialized form), you'll have to somehow send the version back to the server.
As I said in the issue, this cannot be done by simply making the version property available in the proxy and setting it; but you could add another property: getting it would always return null (or similar nonexistent value), so that setting it on the client-side to the value of the "true" version property would always produce a change, which guaranties the value will be sent to the server as part of the "property diff"; and on the server-side, you could handle things either in the setter (when RequestFactory applies the "property diff" and calls the setter, if the value is different from the "true" version, then throw an exception) or in the service methods (compare the version sent from the client –which you'd get from a different getter than the one mapped on the client, as that one must always return null– to the "true" version of the object, and raise an error if they don't match).
Something like:
#ProxyFor(MyEntity.class)
interface MyEntityProxy extends EntityProxy {
String getServerVersion();
String getClientVersion();
void setClientVersion(String clientVersion);
…
}
#Entity
class MyEntity {
private String clientVersion;
#Version private String serverVersion;
public String getServerVersion() { return serverVersion; }
public String getClientVersion() { return null; }
public void setClientVersion(String clientVersion) {
this.clientVersion = clientVersion;
}
public void checkVersion() {
if (Objects.equal(serverVersion, clientVersion)) {
throw new OptimisticConcurrencyException();
}
}
}
Note that I haven't tested this, this is pure theory.
We came up with another workaround for optimistic locking in our app. Since the version can't be passed with the proxy itself (as Thomas explained) we are passing it via HTTP GET parameter to the request factory.
On the client:
MyRequestFactory factory = GWT.create( MyRequestFactory.class );
RequestTransport transport = new DefaultRequestTransport() {
#Override
public String getRequestUrl() {
return super.getRequestUrl() + "?version=" + getMyVersion();
}
};
factory.initialize(new SimpleEventBus(), transport);
On the server we create a ServiceLayerDecorator and read version from the RequestFactoryServlet.getThreadLocalRequest():
public static class MyServiceLayerDecorator extends ServiceLayerDecorator {
#Override
public final <T> T loadDomainObject(final Class<T> clazz, final Object domainId) {
HttpServletRequest threadLocalRequest = RequestFactoryServlet.getThreadLocalRequest();
String clientVersion = threadLocalRequest.getParameter("version") );
T domainObject = super.loadDomainObject(clazz, domainId);
String serverVersion = ((HasVersion)domainObject).getVersion();
if ( versionMismatch(serverVersion, clientVersion) )
report("Version error!");
return domainObject;
}
}
The advantage is that loadDomainObject() is called before any changes are applied to the domain object by RF.
In our case we're just tracking one entity so we're using one version but approach can be extended to multiple entities.