To be specific let me illustrate the question with Spring http-remoting example.
Suppose we have such implementation of a simple interface:
public SearchServiceImpl implements SearchService {
public SearchJdo processSearch(SearchJdo search) {
search.name = "a funky name";
return search;
}
}
SearchJdo is itself a simple POJO.
Now when we call the method from a client through http-remoting (Spring's mechanism of calling remote objects much like EJB that uses serialization) we'll get:
public class HTTPClient {
public static void main(final String[] arguments) {
final ApplicationContext context = new ClassPathXmlApplicationContext(
"spring-http-client-config.xml");
final SearchService searchService =
(SearchService) context.getBean("searchService");
SearchJdo search = new SearchJdo();
search.name = "myName";
// this method actually returns the same object it gets as an argument
SearchJdo search2 = searchService.processSearch(search);
System.out.println(search == search2); // prints "false"
}
}
The problem is that the search objects are different because of serializaton although from logical prospective they are the same.
The question is whether there are some technique that allows to support or emulate object identity across VMs.
You said it - object identity is different from logical equality.
object identity is compared with ==
logical equality is compared with .equals(..)
So override the equals() method and all will be fine. Remember to override hashCode() based on the same field(s) as well. Use your IDE to generate these 2 methods for you.
(Teracotta VM clustering allows sharing objects between VMs, but that doesn't fit your case.)
IMHO attempting to preserve object identity equality across VMs is a losing proposition.
To the best of my knowledge the language specification does not require a VM to support that, so you would be limited in where you can pull off if you truly want to be portable.
May I ask why you don't just use some unique ID that you supply yourself? Java GUIDs, while expensive, are serializable.
I did this once, but I'm not quite sure if this is a right approach:
Every user had a username, session id, roles, and a login date attached to a user object. Every time I logged into a VM the system would load a User object into memory; I would also return the user object to the application.
If I needed to execute an action within the application server, then I would send the user object as an argument. If the VM had the User loaded with the same session ID then it would use the object stored in the VM to know the assigned roles. Otherwise, the application would then be capable of changing the roles in the user and it wouldn't be secure.
If the application had to change the application server, then it sends the user object to the new server and the new server wouldn't be able to find the user within its records.
HERE IS THE SECRET: The session ID is created hashing the username, the login date and a secret password shared among all of the servers.
Once the new server finds that the session ID is coherent, then it would load the roles from the database as a reliable source of information.
Sorry if I couldn't write this before, but hope it helps for someone.
Related
In Java Spring Boot, I can easily enable caching using the annotation #EnableCaching and make methods cache the result using #Cacheable, this way, any input to my method with the exact same parameters will NOT call the method, but return immediately using the cached result.
Is there something similar in C#?
What I did in the past was i had to implement my own caching class, my own data structures, its a big hassle. I just want an easy way for the program to cache the result and return the exact result if the input parameters are the same.
EDIT: I dont want to use any third party stuff, so no MemCached, no Redis, no RabbitMQ, etc... Just looking for a very simple and elegant solution like Java's #Cacheable.
Caches
A cache is the most valuable feature that Microsoft provides. It is a type of memory that is relatively small but can be accessed very quickly. It essentially stores information that is likely to be used again. For example, web browsers typically use a cache to make web pages load faster by storing a copy of the webpage files locally, such as on your local computer.
Caching
Caching is the process of storing data into cache. Caching with the C# language is very easy. System.Runtime.Caching.dll provides the feature for working with caching in C#. In this illustration I am using the following classes:
ObjectCache
MomoryCache
CacheItemPolicy
ObjectCache
: The CacheItem class provides a logical representation of a cache entry, that can include regions using the RegionName property. It exists in the System.Runtime.Caching.
MomoryCache
: This class also comes under System.Runtime.Caching and it represents the type that implements an in-cache memory.
CacheItemPolicy
: Represents a set of eviction and expiration details for a specific cache entry.
.NET provides
System.Web.Caching.Cache - default caching mechanizm in ASP.NET. You can get instance of this class via property Controller.HttpContext.Cache also you can get it via singleton HttpContext.Current.Cache. This class is not expected to be created explicitly because under the hood it uses another caching engine that is assigned internally. To make your code work the simplest way is to do the following:
public class DataController : System.Web.Mvc.Controller{
public System.Web.Mvc.ActionResult Index(){
List<object> list = new List<Object>();
HttpContext.Cache["ObjectList"] = list; // add
list = (List<object>)HttpContext.Cache["ObjectList"]; // retrieve
HttpContext.Cache.Remove("ObjectList"); // remove
return new System.Web.Mvc.EmptyResult();
}
}
System.Runtime.Caching.MemoryCache - this class can be constructed in user code. It has the different interface and more features like update\remove callbacks, regions, monitors etc. To use it you need to import library System.Runtime.Caching. It can be also used in ASP.net application, but you will have to manage its lifetime by yourself.
var cache = new System.Runtime.Caching.MemoryCache("MyTestCache");
cache["ObjectList"] = list; // add
list = (List<object>)cache["ObjectList"]; // retrieve
cache.Remove("ObjectList"); // remove
You can write a decorator with a get-or-create functionality. First, try to get value from cache, if it doesn't exist, calculate it and store in cache:
public static class CacheExtensions
{
public static async Task<T> GetOrSetValueAsync<T>(this ICacheClient cache, string key, Func<Task<T>> function)
where T : class
{
// try to get value from cache
var result = await cache.JsonGet<T>(key);
if (result != null)
{
return result;
}
// cache miss, run function and store result in cache
result = await function();
await cache.JsonSet(key, result);
return result;
}
}
ICacheClient is the interface you're extending. Now you can use:
await _cacheClient.GetOrSetValueAsync(key, () => Task.FromResult(value));
I'm creating a web app.
I have a MyUI that extends UI.
public class MyUI extends UI {
public static Authentication AUTH;
#Override
protected void init(VaadinRequest vaadinRequest) {
AUTH = new Authentication();
updateContent();
}
//other methods
}
In Authentication() I have the user logged. When I do the logout, that user is set to null.
I noticed that when I access to the server from two device, so when I should have two connection to the server, when someone do the logout, the other one is logged out too.
In Authentication class there is this method:
public void doLogout() {
System.out.println("User: " + this.user.getMail() + " has logged out.");
this.user = null;
}
I get error in user.getMail() because the user is already set to null, when I try to do the logout from the other account.
Is com.vaadin.ui.UI unique? How can I handle different connections in Vaadin?
Java, in general
Basic Java here, nothing to do with Vaadin…
The keyword static means one value per class, otherwise known as a “class variable”, more generally known as a “global variable”. Not object-oriented. Generally speaking, you should minimize your use of static.
Omitting that keyword means “one value per instance of this class”, an instance variable also known as member variables. This is object-oriented.
I suggest you learn more of the basics of Java before embarking on a Vaadin project. And learn the basics of how Java Servlet technology works, perhaps reading the Head First book on Servlet published by O’Reilly (now outdated, but basics are the same). You also need to learn about advanced topics such as threading and concurrency issues as a Servlet environment such as Vaadin is inherently multi-threaded. Eventually, read the book Java Concurrency In Practice by Goetz.
Vaadin specifically
To store values per user of a Vaadin app, use session attributes. This is a key-value store where you insert and retrieve a value by specifying a key, the name of the "attribute". The session is automatically instantiated for you when the user first connects, as part of the Java Servlet technology.
Alternatively, you can store values per user on that UI class as instance variables. Each Vaadin user starts with a UI instance when first connecting. But beware: you can open multiple web browser tabs/windows in a Vaadin 8 app, each having their own UI instance. So to share data between those multiple UI objects, use the session attributes.
Note that while every Vaadin app has at least one UI subclass defined, you can define additional UI subclasses as well, for those additional browser tabs/windows mentioned above to show different content.
Maybe instead of static variable you should use here session attribute (updated to be more generic):
UI.getCurrent().getSession().setAttribute("AUTH", AUTH);
Authentication auth2 = UI.getCurrent().getSession().getAttribute("AUTH");
So use VaadinSession to store session specific data.
I own a DDD/CQRS application.
My question concerns the handling of an item creation through POST (Rest).
CQRS (based on CQS principle) promotes that commands should never return a value.
Queries are there for that.
So I wonder how to handle the use case of Item creation.
Here's my current command handler pattern (light for the sample (no interfaces etc.)):
#Service
#Transactional
public CreateItem {
public void handle(CreateItemCommand command) {
Customer customer = customerRepository.findById(command.customerId);
ItemId generatedItemId = itemRepository.nextIdentity(); //generating the GUID
customer.createItem(generatedItemId, .....);
}
}
By reading this article, an easy method would be to declare an output property in the command, populated at the end of the handle method like this:
public void handle(CreateItemCommand command) {
Customer customer = customerRepository.findById(command.customerId);
ItemId generatedItemId = itemRepository.nextIdentity(); //generating the GUID
customer.createItem(generatedItemId, .....);
command.itemId = generatedItemId; //populating the output property
}
However, I see one drawback with this approach:
- A command, in theory, is meant to be immutable.
This itemId would then be sent thanks to the calling controller (webapp) through Location Header with the status 201 or 202 (depending if I expect async or not).
An other solution would be to let the controller initialize the GUID by accessing the repository itself, thus letting the command immutable:
//in my controller:
ItemId generatedItemId = itemRepository.nextIdentity(); //controller generating the GUID
createItem.handle(command);
// setting here the location header (201-202) containing the URL to the newly created item with the using the previous itemId.
Drawback: Controller (adapter layer) accessing directly the repository ..., that is too low-level IMO.
My extreme client being a Javascript application, I might have another solution to let the Javascript itself generate a GUID, and feed CreateItemCommand with it before sending the whole command to server.
Advantage: No more issues about potential violation of CQ(R)S guidelines.
Drawback: Should check the validity of the passed id at server side. Although there would have an index unique on this preventing an unexpected insertion in database.
What is the best (or just a good) strategy to handle this?
I am the developer of a CRM application based on the CQRS pattern. I tend to see commands as immutable. The team decided early on, that all IDs are generated on the client to have immutable commands. This is perfectly ok, as we are using UUIDs. So we are quite confident, that the IDs are valid and there are no ID collisions. We went well with that approach up to this point - I can definitely recommend this. In that scenario the client just knows the IDs.
Sometimes it happens though - especially in manual testing - that a create command is dispatched twice with the same ID. In that case the addition of events in the event store fails (we use event sourcing) with a duplicate key exception. The exception is passed to the controller. In fact we do return results from command executions with a call back, even though it's just "everything ok" most of the time - so no exception thrown. Also command validation is done this way. We do this using a command bus concept.
I would recommend taking a look at the Axon framework. We use it, it provides the common building blocks, and it just works. Maybe you can get some inspirations from that!
Can anyone suggest any design pattern to dynamically differentiate the memcahce instances in java code?
Previously in my application there is only one memcache instance configured this way
Step-1:
dev.memcached.location=33.10.77.88:11211
dev.memcached.poolsize=5
Step-2:
Then i am accessing that memcache in code as follows,
private MemcachedInterface() throws IOException {
String location =stringParam("memcached.location", "33.10.77.88:11211");
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(location));
}
Then i am invoking that memcache as follows in code using above MemcachedInterface(),
Step-3:
MemcachedInterface.getSoleInstance();
And then i am using that MemcachedInterface() to get/set data as follows,
MemcachedInterface.set(MEMCACHED_CUSTS, "{}");
resp = MemcachedInterface.gets(MEMCACHED_CUSTS);
My question is if i introduce an new memcache instance in our architechture,configuration is done as follows,
Step-1:
dev.memcached.location=33.10.77.89:11211
dev.memcached.poolsize=5
So, first memcache instance is in 33.10.77.88:11211 and second memcache instance is in 33.10.77.89:11211
until this its ok...but....
how to handle Step-2 and Step-3 in this case,To get the MemcachedInterface dynamically.
1)should i use one more interface called MemcachedInterface2() in step-2
Now the actual problem comes in,
I am having 4 webservers in my application.Previoulsy all are writing to MemcachedInterface(),but now as i will introduce one more memcache instance ex:MemcachedInterface2() ws1 and ws2 should write in MemcachedInterface() and ws3 and ws4 should write in ex:MemcachedInterface2()
So,if i use one more interface called MemcachedInterface2() as mentioned above,
This an code burden as i should change all the classes using WS3 and WS4 to Ex:MemcachedInterface2() .
Can anyone suggest one approach with limited code changes??
xmemcached supports constistent hashing which will allow your client to choose the right memcached server instance from the pool. You can refer to this answer for a bit more detail Do client need to worry about multiple memcache servers?
So, if I understood correctly, you'll have to
use only one memcached client in all your webapps
since you have your own wrapper class around the memcached client MemcachedInterface, you'll have to add some method to this interface, that enables to add/remove server to an existing client. See the user guide (scroll down a little): https://code.google.com/p/xmemcached/wiki/User_Guide#JMX_Support
as far as i can see is, you have duplicate code running on different machines as like parallel web services. thus, i recommend this to differentiate each;
Use Singleton Facade service for wrapping your memcached client. (I think you are already doing this)
Use Encapsulation. Encapsulate your memcached client for de-couple from your code. interface L2Cache
For each server, give them a name in global variable. Assign those values via JVM or your own configuration files via jar or whatever. JVM: --Dcom.projectname.servername=server-1
Use this global variable as a parameter, configure your Service getInstance method.
public static L2Cache getCache() {
if (System.getProperty("com.projectname.servername").equals("server-1"))
return new L2CacheImpl(SERVER_1_L2_REACHIBILITY_ADDRESSES, POOL_SIZE);
}
good luck with your design!
You should list all memcached server instances as space separated in your config.
e.g.
33.10.77.88:11211 33.10.77.89:11211
So, in your code (Step2):
private MemcachedInterface() throws IOException
{
String location =stringParam("memcached.location", "33.10.77.88:11211 33.10.77.89:11211");
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(location));
}
Then in Step3 you don't need to change anything...e.g. MemcachedInterface.getSoleInstance(); .
You can read more in memcached tutorial article:
Use Memcached for Java enterprise performance, Part 1: Architecture and setup
http://www.javaworld.com/javaworld/jw-04-2012/120418-memcached-for-java-enterprise-performance.html
Use Memcached for Java enterprise performance, Part 2: Database-driven web apps
http://www.javaworld.com/javaworld/jw-05-2012/120515-memcached-for-java-enterprise-performance-2.html
These two seem to be doing the same things. Can anyone explain the main difference between the two? When would you use one vs the other?
HttpServletRequest.getRemoteUser()
HttpServletRequest.getUserPrincipal().getName()
A Principal represents someone who could potentially authenticate with your application. The Principal's name depends on the authentication method used:
a username such as "fred" (in the case of HTTP Basic authentication)
a Distinguished Name such as "CN=bob,O=myorg" (in the case of X.509 client certificates - in which case a X500Principal may be returned)
getRemoteUser() returns "the login of the user" which, in the case of HTTP Basic authentication, will also be the username; it doesn't map cleanly in the X.509 client certificate case though, since the user doesn't enter a "login" as such - in the example above, we could use the Distinguished Name or simply the CN, "bob".
The Javadocs state that "whether the user name is sent with each subsequent request depends on the browser and type of authentication", suggesting that getRemoteUser() was originally meant to provide data only for requests in which a username was entered. This, however, would result in it returning null for the majority of requests when cookie-based auth is in use - not too helpful!
In reality, getRemoteUser() often just calls getUserPrincipal().getName(); verified in Tomcat 6 and Jetty 6/7.
The getUserPrincipal() method returns an object of some class derived from the Principal interface, which is an abstraction of the entity that is the "user" responsible for the request. From it you get an actual object that, depending on the implementing class, you can use to get all sorts of information about that user/identity. One of those properties is the string-representation of the name of the user/identity, which you obtain by calling getName().
getRemoteUser() is really just a shortcut to getting that string-representation. You don't have access to any other methods implemented by the implementing class, not do you have access to the object itself, just the string-representation of the name.
For most use-cases that I am familiar with, that string-representation is what you want; I believe this is why getRemoteUser() exists - it's a common case so there's an easy/quick way to get access to it without actually getting a reference to an implementing class object.
A bit related issue:
People converting older IBM Portlet API code to JSR168 one had to change PortletRequest to HttpServletRequest in some method parameters, but then from WPS6.1 and up they can't cast that to PortletRequest (it doesn't implement the respective interface anymore as it seems) and if they call "getRemoteUser" directly on the HttpServletRequest they get back null (some say a workarround is to enable application security option in WAS [WebSphere Application Server], others say more security-related markup is needed in web.xml)
A workarround seems to be to use PUMA, but of course that is IBM WebSphere specific. Probably at other Portlet Containers there are other vendor-specific workarrounds if one finds that getRemoteUser always returns null (judging from other replies then getUserPrincipal().getName() also returns null if getRemoteUser is implemented as just a shortcut to that one).
BTW, the PUMA code I mention above is here, since it's a bit hard to find what works in WPS6.1+:
import com.ibm.portal.portlet.service.PortletServiceHome;
import com.ibm.portal.um.*;
import com.ibm.portal.um.exceptions.PumaException;
import com.ibm.portal.puma.User;
//...
public String getCurrentUser(){
try {
Context ctx = new InitialContext();
Name myjndiname = new CompositeName(PumaHome.JNDI_NAME);
PumaHome myHome = (PumaHome) ctx.lookup(myjndiname);
if (myHome!=null) {
PumaProfile pumaProfile = myHome.getProfile();
com.ibm.portal.um.User user = (com.ibm.portal.um.User)pumaProfile.getCurrentUser();
List attributes = new ArrayList();
attributes.add("uid");
Map userAttributes = pumaProfile.getAttributes(user,attributes);
return (String) userAttributes.get("uid");
}
}