I've recently began on working on my first CORBA project. I think I got the basic stuff , however there are some things that still elude me. One of these things is how CORBA handles several calls on the same object .
Suppose I have a client that registers itself with the server , and then can receive work. The server sends work at random times.
Are all these calls handled on the same thread ? This would mean that while the client is working , it cannot receive anything. In this case how could I give him a multithread behavior.
Or on the other hand is a thread spawned for every call received ?. In this case do I need to protect the common data that can be accessed on each call ? What would be a good practice to do so
Other thing I'd like to do is to create several workers and have them receive work ,but in my implementation only one worker is active .
Below :
public static void main(String[] args)
{
try
{
connectWithServer(args);
createWorkers();
// wait for invocations from clients
orb.run();
}
catch (Exception e)
{
System.out.println("ERROR : " + e) ;
e.printStackTrace(System.out);
}
}
static public void connectWithServer(String[] args)throws Exception
{
orb = ORB.init(args, null);
// get reference to rootpoa & activate the POAManager
rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
rootpoa.the_POAManager().activate();
// get the root naming context
org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
// Use NamingContextExt instead of NamingContext. This is
// part of the Interoperable naming Service.
NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
// resolve the Object Reference in Naming
taskBagImpl = TaskBagHelper.narrow(ncRef.resolve_str(SERVER_NAME));
System.out.println(TAG + " Obtained a handle on server object: " + taskBagImpl);
}
public static void createWorkers() throws Exception
{
for(int i = 0; i < nrOfWorkers; i++)
{
WorkerImpl w = new WorkerImpl();
rootpoa.activate_object((Servant) w);
Worker ref = WorkerHelper.narrow(rootpoa.servant_to_reference(w));
w.setRef(ref);
taskBagImpl.registerWorker(w.getId(), ref);
}
}
Threading options are not specified in the CORBA standard. The only configuration possible in respect to threading is the POA policy ThreadingPolicy. Possible values are either ORB_CTRL_MODEL or SINGLE_THREAD_MODEL. The former specifies nothing about threading, and the ORB implementation decides which threading model to use. The latter guarantees that every request that an object receives (within the same POA) is serialized, so no re-entrancy or multi-threading capabilities has to be implemented in the servant.
CORBA implementors, however, took notice of this limitation and implemented some standard default policies, that have to be configured by other means (maybe program options via ORB.init() or configuration files). Usually, you can find three different policies (once you select ORB_CTRL_MODEL):
Thread per request: Spawns a new thread each request.
Thread per client: Spawns a new thread for each different client.
Thread pool: The ORB pre-allocates some pool of threads and uses them to serve all requests.
Others are possible, but those tend to be the common ground. Of couse, either of them will force you to use any kind of locking strategy to support concurrent clients.
See this Java IDL FAQ :
What is the thread model supported by the CORBA implementation in this release?
Related
I'm writing a spring-boot based project where I have some synchronous (eg. RESTI API calls) and asynchronous (JMS) pieces of code (the broker I use is a dockerized instance of ActiveMQ in case there's some kind of trick/workaround).
One of the problems I'm currently struggling with is: my application receives a REST api call (I'll call it "a sync call"), it does some processing and then sends a JMS message to a queue (async) whose message in then handled and processed (let's say I have a heavy load to perform, so that's why I want it to be async).
Everything works fine when running the application, async messages are enqueued and dequeued as expecting.
When I'm writing tests, (and I'm testing the whole service, which includes the sync and async call in rapid succession) it happens that the test code is too fast, and the message is still waiting to be dequeued (we are talking about milliseconds, but that's the problem).
Basically as soon as i receive the response from the API call, the message is still in the queue, so if, for example I make a query to check for its existence -> ka-boom the test fails because (obviously) it doesn't find the object (that probably meanwhile is being processed and created).
Is there any way, or any pattern, I can use to make my test wait for that async message to be dequeued? I can attach code to my implementation if needed, It's a bachelors degree thesis project.
One obvious solution I'm temporarily using is adding a hundred milliseconds sleep between the method call and the assert section (hoping everything is done and persisted), but honestly I kinda dislike this solution because it seems so non-deterministic to me. Also creating a latch between development code and testing doesn't sound really good to me.
Here's the code I use as an entry-point to al the mess I explained before:
public TransferResponseDTO transfer(Long userId, TransferRequestDTO transferRequestDTO) {
//Preconditions.checkArgument(transferRequestDTO.amount.compareTo(BigDecimal.ZERO) < 0);
Preconditions.checkArgument(userHelper.existsById(userId));
Preconditions.checkArgument(walletHelper.existsByUserIdAndSymbol(userId, transferRequestDTO.symbol));
TransferMessage message = new TransferMessage();
message.userId = userId;
message.symbol = transferRequestDTO.symbol;
message.destination = transferRequestDTO.destination;
message.amount = transferRequestDTO.amount;
messageService.send(message);
TransferResponseDTO response = new TransferResponseDTO();
response.status = PENDING;
return response;
}
And here's the code that receives the message (although you wouldn't need it):
public void handle(TransferMessage transferMessage) {
Wallet source = walletHelper.findByUserIdAndSymbol(transferMessage.userId, transferMessage.symbol);
Wallet destination = walletHelper.findById(transferMessage.destination);
try {
walletHelper.withdraw(source, transferMessage.amount);
} catch (InsufficientBalanceException ex) {
String u = userHelper.findEmailByUserId(transferMessage.userId);
EmailMessage email = new EmailMessage();
email.subject = "Insufficient Balance in your account";
email.to = u;
email.text = "Your transfer of " + transferMessage.amount + " " + transferMessage.symbol + " has been DECLINED due to insufficient balance.";
messageService.send(email);
}
walletHelper.deposit(destination, transferMessage.amount);
String u = userHelper.findEmailByUserId(transferMessage.userId);
EmailMessage email = new EmailMessage();
email.subject = "Transfer executed";
email.to = u;
email.text = "Your transfer of " + transferMessage.amount + " " + transferMessage.symbol + " has been ACCEPTED.";
messageService.send(email);
}
Im' sorry if the code sounds "a lil sketchy or wrong" it's a primordial implementation.
I'm willing to write a utility to share with you all if that's the case, but, as you've probably noticed, I'm low on ideas right now.
I'm an ActiveMQ developer working mainly on ActiveMQ Artemis (the next-gen broker from ActiveMQ). We run into this kind of problem all the time in our test-suite given the asynchronous nature of the broker, and we developed a little utility class that automates & simplifies basic polling operations.
For example, starting a broker is asynchronous so it's common for our tests to include an assertion to ensure the broker is started before proceeding. Using old-school Java 6 syntax it would look something like this:
Wait.assertTrue(new Condition() {
#Override
public boolean isSatisfied() throws Exception {
return server.isActive();
}
});
Using a Java 8 lambda would look like this:
Wait.assertTrue(() -> server.isActive());
Or using a Java 8 method reference:
Wait.assertTrue(server::isActive);
The utility is quite flexible as the Condition you use can test anything you want as long as it ultimately returns a boolean. Furthermore, it is deterministic unlike using Thread.sleep() (as you noted) and it keeps testing code separate from the "product" code.
In your case you can check to see if the "object" being created by your JMS process can be found. If it's not found then it can keep checking until either the object is found or the timeout elapses.
So if I have a socket server, I can accept each socket and pass it to a executory
while(true){
Socket conn = socketServ.accept();
Runnable task = new Runnable() {
#Override
public void run() {
try{
server.executor(conn);
} catch(IOException e){
}
}
};
exec1.execute(task);
}
Doing this allows my server to run on my threads and does not block the same thread. Because I also have reference to that socket... called "conn" I can successfully return messages as well.
Now I have an RMI interface, which basically lets me call methods back and forth.
for example if I had this method:
public MusicServerResponseImpl CreatePlayerlist(String Name, UserObjectImpl uo) throws RemoteException {
MusicServerResponseImpl res = new MusicServerResponseImpl();
return res;
}
Which returns a serializable object. My concern is when this message gets called, I think it is going to get called in the main thread of the server, and thus will block that thread and slow down parallelism.
What I think is the solution is to have every single RMI method also create a task for an executor.. to speed up the execution of everything...this issue I am seeing however is unlike the socket where I have an object to send information back to, I am unsure how I would return a response from the RMI method, without somehow having to block the thread.
Does that make sense? Basically I am asking how I can execute in parallel with RMI methods while still being able to return results!
Thanks for the help!
Does that make sense?
No. Concurrent calls are natively supported.
See this documentation page and look for the property named maxConnectionThreads.
You could also have tested your assumptions by, for example, printing the current thread name in your server code, and trying to execute concurrent calls and see what happens.
I have a working Thrift client in the below snippet.
TTransport transport = new THttpClient(new Uri("http://localhost:8080/api/"));
TProtocol protocol = new TBinaryProtocol(transport);
TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "UserService");
UserService.Client userServiceClient = new UserService.Client(mp);
System.out.println(userServiceClient.getUserById(100));
When running the client within multi-threaded environment
threads[i] = new Thread(new Runnable() {
#Override
public void run() {
System.out.println(userServiceClient.getUserById(someId));
}
}
I got an exception: out of sequence response
org.apache.thrift.TApplicationException: getUserById failed: out of sequence response
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:76)
I guess the reason is that Thrift generated Client is not thread safe.
But if I want multi-clients to call the same method getUserById() simultaneously, how can I make it?
Thrift clients are not designed to be shared across threads. If you need multiple client threads, set up one Thrift client per thread.
But if I want multi-clients to call the same method getUserById() simultaneously, how can I make it?
We don't know much about the context, so I have to guess a bit. If the issue is that there are a lot of such calls coming in at a time, a possible solution could be to group calls to save roundtrip time:
service wtf {
list<string> getUsersById( 1 : list<int> userIds)
}
That's just a short idea. Maybe you want to return list<user_data_struct> instead. For practical reasons I would also recommend to wrap the returned list into a struct, so the whole thing becomes extensible.
I have a distributed application using java RMI and a main object(CoreApplication) that implements java.io.Serializable. Every minute, this main object is sent to a remote computer and processed on that JVM's thread pool. Since it's asynchronous, the object is processed without blocking the main thread on the Master computer.
When the CoreApplication object is finished processing on the remote thread, it invokes a call back method and is sent back to the main computer.
Here is some code of the remote machine processing a job invoked from the Master computer via RMI and the sendJob method
public void sendJob(final CoreApplication aJob) throws RemoteException{
Runnable r = new Runnable(){
public void run(){
try {
WorkResponse wr = aJob.process();
client.coreApplicationHandler(aJob,wr);
}catch(RemoteException e){}
}
};
workQueue.execute(r);
}
You can see client.coreApplicationHandler is the callback method to the main server and sends the CoreApplication object back with it, along with a response object.
Here is the coreApplicationHandler method code on the main machine
public void coreApplicationHandler(CoreApplication j,WorkResponse wr){
String ticker = j.getTickerSymbol();
coreApplicationObjects.put(ticker, j);
if(GlobalParameters.DEBUG_MODE){
System.out.println("WORK RESPONSE IS "+wr.getMessage());
}
}
My question is, is replacing the CoreApplication object each time on the call back method the best way to make sure it's up-to-date for the next minute it's sent? CoreApplication is fluid and changes and the state must be preserved. I am sending it back to the Master computer, so it's state can be monitored from a central location. If I had 100 computation nodes and they didn't return their objects, it would get really messy I think to keep track of them all.
It works pretty good so far unless the job isn't processed by the time it tries to send out another and results in sending a stale object with an old state (ie, the same object as the last minute). Please comment if this doesn't make sense and I will do my best to explain it.
RMI is not a way to synchronize objects across a cluster. But there are tools to do just that. Look at http://www.hazelcast.com/, for example.
If you have a cluster of computers and need synchronization then you need to use clustering via the server's tools or a third party tool.
I recommend hazelcast. It is very easy to use and will allow local clusters using fast UDP or WAN clusters using TCP socket to TCP socket.
For example Hazelcast will let you do something like this:
import com.hazelcast.core.MultiMap;
import com.hazelcast.core.Hazelcast;
import java.util.Collection;
// a live shared multimap shared across all cluster nodes
MultiMap<String, Order> mmCustomerOrders = Hazelcast.getMultiMap("customerOrders");
mmCustomerOrders.put("1", new Order ("iPhone", 340));
Thread.Sleep( 1000 );
Order order = (Order) mmCustomerOrders.get("1");
System.out.println( Order.quantity() ); // 340 ?? Nobody knows, it might have been changed
What is the output? If a cluster member changed the item "1" in the map, then you will get that value automagically. No more coding necessary….
Hope it helps
-Alex
I don't have much knowledge on Java EE but am currently learning it.
I've come up with a project which involves a long running task (up to several minutes) invoked by the user. The task consists of several steps. Of course I would like to show the progress to the user.
The project uses Java EE with JPA, JSF and Icefaces. It runs on Glassfish.
An experienced colleague adviced the following pattern to me:
Create a stateless, asynchronous EJB which creates a response object and processes the request
Persist the response object after each step
In the backing bean, query and display the response object
This works well. My only problem is to update the status site to mirror the progress. Currently I am doing this with a simple JavaScript page reload every x seconds.
Do you know a way/pattern to reflect the current step from the stateless ejb to the jsf backing bean?
Or, and I would prefer that, do you know a way to query the value of a backing bean every x seconds?
Edit:
I am aware of the Icefaces push mechanism, but I want the status update site to be decoupled from the calculation EJB for the following reasons:
The backing bean might already be destroyed because the user left the site and return later to fetch the result
Multiple sessions and therefore multiple beans may exist for one user
Having a clean design
There are several options to pass back this information. If EJB is living in the same JVM,
you may as well use some singleton Map and store progress under certain key (session ID)
If this is not the case, you will need some shared state or comminucation. There are several options
store it on database accessible from both tiers ( sql, JNDI, LDAP - better solution would be key-value store , like redis - if you got it )
use some messaging to deposit state of processing on web tier side
store state in a hash it on EJB tier side, and provide another SLSB method to rtrieve this state
Your choice is not easy - all of these solution suckin a different ways.
I accomplished this using a threaded polling model in conjunction with a ProgressBar component.
public void init()
{
// This method is called by the constructor.
// It doesn't matter where you define the PortableRenderer, as long as it's before it's used.
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
}
public void someBeanMethod(ActionEvent evt)
{
// This is a backing bean method called by some UI event (e.g. clicking a button)
// Since it is part of a JSF/HTTP request, you cannot call portableRenderer.render
copyExecuting = true;
// Create a status thread and start it
Thread statusThread = new Thread(new Runnable() {
public void run() {
try {
// message and progress are both linked to components, which change on a portableRenderer.render("fullFormGroup") call
message = "Copying...";
// initiates render. Note that this cannot be called from a thread which is already part of an HTTP request
portableRenderer.render("fullFormGroup");
do {
progress = getProgress();
portableRenderer.render("fullFormGroup"); // render the updated progress
Thread.sleep(5000); // sleep for a while until it's time to poll again
} while (copyExecuting);
progress = getProgress();
message = "Finished!";
portableRenderer.render("fullFormGroup"); // push a render one last time
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
});
statusThread.start();
// create a thread which initiates script and triggers the termination of statusThread
Thread copyThread = new Thread(new Runnable() {
public void run() {
File someBigFile = new File("/tmp/foobar/large_file.tar.gz");
scriptResult = copyFile(someBigFile); // this will take a long time, which is why we spawn a new thread
copyExecuting = false; // this will caue the statusThread's do..while loop to terminate
}
});
copyThread.start();
}
As you are using icefaces you could use the ICEpush mechanism for rendering your updates.