CORBA - Advanced example with server-client in Java and C++

From XennisWiki
Jump to: navigation, search

In this article a server-client application is described, which is realised with an Java server and a C++ and Java client using CORBA. The application is about a quiz game. The client can:

  • insert a question: The client can create questions with multiple answers and sent it to the server. The server will store the question and return the ID of it to the client.
  • get a question: The client requests a question. The server returns a random question (of all stored questions) to the client.
  • answer a question: The client gives an answer for a question. The server checks the answer and returns the result (and the correct answers).
  • delete a question: The client sends a ID to the server, which will delete the corresponding question.

A question has multiple answers and one ore more correct answers. In this article a interactive Java client with a command line interface and a non-interactive C++ client is described.

Note: This article based on the CORBA article, in which a really simple server-client application with JAVA and C++ is described. If you used CORBA never before, it is recommended to read this article first.

Project

Used platforms and software

  • Lubuntu 13.04 as operating system in a virtual machine
  • omniORB 4.1.7 as CORBA C++ implementation
  • Java 7 in which CORBA is already included

Structure

The folders and files in brackets are create by the IDL Java and C++ compilers.

My_CORBA_project
  + cpp
  |  |- (client)
  |  |- client.cpp
  |  |- Makefile
  |  |- (Quiz.hh)
  |  |- (QuizSK.cc)
  |
  + java
  |  + client
  |  |  |- QuizClientInteractive.java
  |  |
  |  + Quiz
  |  |  + (CompleteQuestionPackage)
  |  |  |  |- [...] 
  |  |  |
  |  |  + (QuestionPackage)
  |  |  |  |- [...] 
  |  |  |
  |  |  + (QuizServerPackage)
  |  |  | - [...]
  |  |  |
  |  |  |- AnswerImpl.java
  |  |  |- CompleteQuestionImpl.java
  |  |  |- QuestionImpl.java
  |  |  |- [...]
  |  |
  |  + server
  |    - QuizServant.java
  |    - QuizServer.java
  |
  |- Quiz.idl
  |- run

IDL file

Quiz.idl

/* 
 * This module defines the data structure for the quiz game and the interface
 * for the server.
 */
module Quiz {

	/*
	 * Data structure defining a answer for a question.
	 */
	valuetype Answer {
		public char id;
		public string sentence;
	};

	/*
	 * Data structure defining a question with an id, sentence and multiple
	 * answers.
	 */
	valuetype Question {
        typedef sequence<Answer> AnswerSeq;
		public long id;
		public string sentence;
		public AnswerSeq answers;
	};
	
	/*
	 * Data structure defining a complete question. It extends the question
	 * structure by adding (multiple) correct answers.
	 */
	valuetype CompleteQuestion : Question {
		/* Type definition of a char sequence. */
        typedef sequence<char> CharSeq;
		public CharSeq correctAnswers;
	};

	/*
	 * Interface for the quiz server object. This interface provides all
	 * methods, that can used by clients to play the game.
	 */
	interface QuizServer {
	
		/*
		 * Exception type that can be generated by the quiz server object.
		 */
		exception QuizException {
        	        string message;
    	        };

		/* Type definition of a char sequence for the answers */
		typedef sequence<char> answersIds;
	
		/*
		 * Returns a random question to the client. Note: return just a
		 * question without the correct answers, that means return no
		 * complete question.
		 */
		boolean getQuestion(out Question randomQuestion) 
			raises (QuizException);

		/*
		 * Method for creating a new question on the server object. The
		 * CompleteQuestion object is created on the client and sent to the
		 * server by using this method. The server saves this question.
		 *
		 * The method returns the ID of the create question.
		 */
		long insertQuestion(in CompleteQuestion question) 
			raises (QuizException);
	
		/*
		 * Method for answering a question with a given question ID. The server
		 * will check the answers and return true or false. The correct answers
		 * should be written in the out correct parameters.
		 */
		boolean answerQuestion(in long questionId, in answersIds answer, out answersIds correct) 
			raises (QuizException);
	
		/*
		 * Deletes the question with the given ID.
		 */
		long deleteQuestion(in long questionId) 
			raises (QuizException);
 
	};
	
};

Configuration

The following omniORB configuration was used, which you find in /etc/omniORB.cfg. The InitRef was set as localhost with the port number 4333:

InitRef = NameService=corbaname::localhost:4333

The supportBootstrapAgent was activated by set it equal one to allow the communication with Java:

supportBootstrapAgent = 1

Code

Java server

Server

server/QuizServer.java

package server;

import org.omg.CORBA.ORB;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;

import Quiz.QuizServerHelper;

public class QuizServer {

	public static final String SERVER_NAME = "Quiz";
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);

			// get reference to rootpoa & activate the POAManager
			POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
			rootpoa.the_POAManager().activate();

			// create servant and register it with the ORB
			QuizServant helloImpl = new QuizServant();

			// get object reference from the servant
			org.omg.CORBA.Object ref = rootpoa.servant_to_reference(helloImpl);
			Quiz.QuizServer href = QuizServerHelper.narrow(ref);

			// get the root naming context
			org.omg.CORBA.Object objRef =
					orb.resolve_initial_references("NameService");
			// Use NamingContextExt which is part of the Interoperable
			// Naming Service (INS) specification.
			NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

			// bind the Object Reference in Naming
			NameComponent path[] = ncRef.to_name(SERVER_NAME);
			ncRef.rebind(path, href);

			System.out.println("QuizServer ready and waiting ...");

			// wait for invocations from clients
			orb.run();
		} 

		catch (Exception e) {
			System.err.println("ERROR: " + e);
			e.printStackTrace(System.out);
		}

		System.out.println("HelloServer Exiting ...");	}

}

Servant

server/QuizServant.java

package server;


import Quiz.CompleteQuestion;
import Quiz.QuestionHolder;
import Quiz.QuestionImpl;
import Quiz.QuizServerPOA;
import Quiz.QuizServerPackage.QuizException;
import Quiz.QuizServerPackage.answersIdsHolder;

import java.util.*;

public class QuizServant extends QuizServerPOA {

	/** Counter for the question IDs */
	private int numQuestions;
	
	/** Map to save questions */
	private Map<Integer, CompleteQuestion> compleQuestions;

	public QuizServant() {
		this.numQuestions = 0;
		this.compleQuestions = new HashMap<Integer, CompleteQuestion>();
	}

	@Override
	public int insertQuestion(CompleteQuestion question) throws QuizException {
		System.out.println("> receive new question " + question);
		question.id = this.numQuestions++;
		// add to map
		this.compleQuestions.put(question.id, question);
		System.out.println("send question id: " + question.id);
		return question.id;
	}

	@Override
	public boolean getQuestion(QuestionHolder randomQuestion)
			throws QuizException {
		System.out.println("> receive random question request");
		if (!this.compleQuestions.isEmpty()) {
			// Get random complete question
			CompleteQuestion question = this.compleQuestions.get(getRandomMapKey());
			randomQuestion.value = new QuestionImpl(question.id, question.sentence, question.answers);
			System.out.println("send question: " + randomQuestion.value);
			return true;
		} else {
			return false;
		}
	}

	@Override
	public boolean answerQuestion(int questionId, char[] answer,
			answersIdsHolder correct) throws QuizException {

		if (this.compleQuestions.containsKey(questionId)) {
			char[] correctAnswers = compleQuestions.get(questionId).correctAnswers;
			correct.value = correctAnswers;

			// Answer is wrong in this case
			if (answer.length != correctAnswers.length) {
				// System.out.print("Different answer lenght");
				return false;
			}

			boolean flag = true;
			for (int i = 0; i < answer.length; i++) {
				flag = flag & (answer[i] == correctAnswers[i]);
			}
			return flag;

		} else {
			System.err.println("Question ID exits not.");
			return false;
		}

	}

	@Override
	public int deleteQuestion(int questionId) throws QuizException {
		if (this.compleQuestions.containsKey(questionId)) {
			compleQuestions.remove(questionId);
			return questionId;
		} else {
			System.err.println("Quesiton ID exits not.");
			return -1;
		}
	}

	/**
	 * Get a random key from the map this.compleQuestions.
	 * 
	 * @return random map key
	 */
	private Integer getRandomMapKey() {
		List<Integer> mapKeys = new ArrayList<Integer>(this.compleQuestions.keySet());
		int randomIndex = (int) (Math.random() * mapKeys.size());
		return mapKeys.get(randomIndex);
	}

}

Implementations

Quiz/AnswerImpl

package Quiz;

@SuppressWarnings("serial")
public class AnswerImpl extends Answer {

	public AnswerImpl() {
	}
	
	public AnswerImpl(char id, String sentence) {
		this.id = id;
		this.sentence = sentence;
	}

	@Override
	public String toString() {
		return "AnswerImpl [id=" + id + ", sentence=" + sentence + "]";
	}
}

Quiz/CompleteQuestionImpl

package Quiz;

import java.util.Arrays;

import Quiz.CompleteQuestion;

@SuppressWarnings("serial")
public class CompleteQuestionImpl extends CompleteQuestion {

	public CompleteQuestionImpl() {
	}
	
	public CompleteQuestionImpl(String sentence, Answer answers[], char[] correctAnswers) {
		this.sentence = sentence;
		this.answers = answers;
		this.correctAnswers = correctAnswers;
	}

	@Override
	public String toString() {
		return "CompleteQuestionImpl [correctAnswers="
				+ Arrays.toString(correctAnswers) + ", id=" + id
				+ ", sentence=" + sentence + ", answers="
				+ Arrays.toString(answers) + "]";
	}
	
}

Quiz/QuestionImpl.java

package Quiz;

import java.util.Arrays;

import Quiz.Question;

@SuppressWarnings("serial")
public class QuestionImpl extends Question {

	public QuestionImpl() {
	}
	
	public QuestionImpl(int id, String sentence, Answer answers[]) {
		this.id = id;
		this.sentence = sentence;
		this.answers = answers;
	}

	@Override
	public String toString() {
		return "QuestionImpl [id=" + id + ", sentence=" + sentence
				+ ", answers=" + Arrays.toString(answers) + "]";
	}
}

Java interactive client

client/.java

package client;

import java.io.*;
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;

import Quiz.AnswerImpl;
import Quiz.Answer;
import Quiz.CompleteQuestion;
import Quiz.CompleteQuestionImpl;
import Quiz.Question;
import Quiz.QuestionHolder;
import Quiz.QuizServerHelper;
import Quiz.QuizServerOperations;
import Quiz.QuizServerPackage.QuizException;
import Quiz.QuizServerPackage.answersIdsHolder;

public class QuizClientInteractive {

	private static QuizServerOperations serverImpl;
	private static BufferedReader reader;
	
	public static final String SERVER_NAME = "Quiz";	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);

			// 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
			serverImpl = QuizServerHelper.narrow(ncRef.resolve_str(SERVER_NAME));
			
			/*
			 * Start
			 */
			System.out.println("Welcome to the Quiz Client.");
			reader = new BufferedReader(new InputStreamReader(System.in));
			showMenuDialog();
            
		} catch (Exception e) {
			System.out.println("ERROR : " + e) ;
			e.printStackTrace(System.out);
		}	
	}
	private static void showMenuDialog(){
		try {
			
			System.out.println("\n------ Please choose an option:");
	    	System.out.println("a: Insert a new question");
	    	System.out.println("b: Request a random question");
	    	System.out.println("c: Remove a question");
	    	
	        String option = reader.readLine();
	        
	        switch(option) {
		        case "a": insertQuestion(); break;
		        case "b": newRandomQuestion(); break;
		        case "c": removeQuestion(); break;
		        default: returnToMenu(); break;
	        }
	        
		} catch(IOException e) {
        	System.out.println("IOException " + e);
        } catch(QuizException e) {
        	System.out.println("QuizException " + e);
        } catch(Exception e) {
        	System.out.println("Exception " + e);
        }
        
	}
	
	/**
	 * Remove a question.
	 * 
	 * @throws IOException
	 * @throws QuizException
	 */
	private static void removeQuestion() throws IOException, QuizException {
		System.out.println("Write the ID of the question that you would like to remove");
		int questionId = readInteger();
		serverImpl.deleteQuestion(questionId);
			
		returnToMenu();
	}
	
	/**
	 * Get a random question and answer it.
	 * 
	 * @throws IOException
	 * @throws QuizException
	 */
	private static void newRandomQuestion() throws IOException, QuizException {
			System.out.println("------ Request Question");
			
			/*
			 * Get random question from server
			 */
			QuestionHolder myQuestionHolder = new QuestionHolder();
			serverImpl.getQuestion(myQuestionHolder);
			Question receivedQuestion = myQuestionHolder.value;
			
			/*
			 * Print question and alternatives
			 */
			System.out.println("The question is: " + receivedQuestion.sentence);
			Answer[] answers = receivedQuestion.answers;
			for(int i=0; i<answers.length; i++) {
				System.out.println(answers[i].id + ": " + answers[i].sentence);
			}
			
			/*
			 * Answer question
			 */
			System.out.println("Which is the correct answer? Write the letters followed by a comma (,) in order if there are more than one correct answer");
			String correctAnswers = reader.readLine();
			String[] correct = correctAnswers.split(",");
			char[] correctA = new char[correct.length];
			
			for (int i=0; i < correct.length; i++) {
				correctA[i] = correct[i].charAt(0);
			}
			answersIdsHolder correctAnswersHolder = new answersIdsHolder();
			boolean answerIsCorrect = serverImpl.answerQuestion(receivedQuestion.id, correctA, correctAnswersHolder);
			if(answerIsCorrect) {
				System.out.println("Correct answer!");
			} else { 
				System.out.println("You're wrong, I'm sorry! These are the correct answers:");
				System.out.println(correctAnswersHolder.value);
			}
			
			returnToMenu();		
	}
	
	
	private static void insertQuestion() throws IOException, QuizException {
	        System.out.println("------ Insert your new question:");
	        String question = reader.readLine();
	        
	        int howManyAlt = 0;
	        String alternative = null;
	        int howManyCorr = 0;
	        //int count = 0;
	        char[] myCorrectAlternatives = new char[0];
	        int currcount = 0;
	        Answer[] alternatives = new Answer[0];
	   
	        
        	System.out.println("How many alternative would you like to insert? ");
	        howManyAlt = readInteger();
	        
	        alternatives= new Answer[howManyAlt];
	        
	        System.out.println("How many alternative are correct? ");
	        howManyCorr = readInteger();			        
	        myCorrectAlternatives = new char[howManyCorr];	        
	        
	        for(int count = 0; count < howManyAlt; count++) {
		        System.out.println("Write your alternative! ");
			    alternative = reader.readLine();
		        alternatives[count] = new AnswerImpl(((char)(count+65)), alternative);
		        
		        if (currcount < howManyCorr) {
			        System.out.println("Is it correct? Y or N ");
				    if(readYes()){
				    	myCorrectAlternatives[currcount] = ((char)(count+65));
				    	currcount ++;
				    }
		        }
	        }

	        /*
	         * Create question and send it to the server
	         */
	        CompleteQuestion myQuestion = new CompleteQuestionImpl(question, alternatives, myCorrectAlternatives);
	    	int receivedQuestionId = serverImpl.insertQuestion(myQuestion);
	    	System.out.println("> reseived question id: " + receivedQuestionId);
	    	
	    	returnToMenu();
	}

	/**
	 * Shows dialog to return to the menu or quit.
	 * 
	 * @throws IOException
	 */
	private static void returnToMenu() throws IOException {
		System.out.println("Would you like to do somenthing else? Y or N");
    	if(readYes()){
    		showMenuDialog();
    	} else {
    		System.out.println("Goodbye. Quit.");		
    	}
	}
	
	/**
	 * Reads a line and pares it to an integer.
	 * 
	 * @return Read integer
	 * @throws IOException
	 */
	private static int readInteger() throws IOException {
		try {
			return Integer.parseInt(reader.readLine());
		} catch (NumberFormatException e) {
			System.err.println("NumberFormatException: Could not parse integer");
			return -1;
		}		
	}
	
	/**
	 * Returns true, when a "Y" or "y" is read.
	 * 
	 * @return True, when read "Y" or "y"
	 * @throws IOException
	 */
	private static boolean readYes() throws IOException {
    	String line = reader.readLine().toLowerCase();
    	return line.equals("y");
	}
	
}

C++ non-interactive client

In the cpp folder:

omniidl bcxx Quiz.idl

client.cpp

#include "Quiz.hh"
#include <iostream>

/** Name is defined in the server */
#define SERVER_NAME		"Quiz"

Quiz::QuizServer_ptr service_server;

using namespace std;

void insert_question(const char* sentence, int numAnswers, Quiz::Answer** answers, int numCorrectAnswers, CORBA::Char* correctAnswers);
void create_questions();

int main(int argc, char ** argv)
{
	try {
		//------------------------------------------------------------------------
		// Initialize ORB object.
		//------------------------------------------------------------------------
		CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);

		//------------------------------------------------------------------------
		// Resolve service
		//------------------------------------------------------------------------
		service_server = 0;

		try {

			//------------------------------------------------------------------------
			// Bind ORB object to name service object.
			// (Reference to Name service root context.)
			//------------------------------------------------------------------------
			CORBA::Object_var ns_obj = orb->resolve_initial_references("NameService");

			if (!CORBA::is_nil(ns_obj)) {
				//------------------------------------------------------------------------
				// Bind ORB object to name service object.
				// (Reference to Name service root context.)
				//------------------------------------------------------------------------
				CosNaming::NamingContext_ptr nc = CosNaming::NamingContext::_narrow(ns_obj);
				
				//------------------------------------------------------------------------
				// The "name text" put forth by CORBA server in name service.
				// This same name ("MyServerName") is used by the CORBA server when
				// binding to the name server (CosNaming::Name).
				//------------------------------------------------------------------------
				CosNaming::Name name;
				name.length(1);
				name[0].id = CORBA::string_dup(SERVER_NAME);
				name[0].kind = CORBA::string_dup("");

				//------------------------------------------------------------------------
				// Resolve "name text" identifier to an object reference.
				//------------------------------------------------------------------------
				CORBA::Object_ptr obj = nc->resolve(name);

				if (!CORBA::is_nil(obj)) {
					service_server = Quiz::QuizServer::_narrow(obj);
				}
			}
		} catch (CosNaming::NamingContext::NotFound &) {
			cerr << "Caught corba not found" << endl;
		} catch (CosNaming::NamingContext::InvalidName &) {
			cerr << "Caught corba invalid name" << endl;
		} catch (CosNaming::NamingContext::CannotProceed &) {
			cerr << "Caught corba cannot proceed" << endl;
		}

		//------------------------------------------------------------------------
		// Do stuff
		//------------------------------------------------------------------------
		if (!CORBA::is_nil(service_server)) {
                        cout << "QuizClient client is running ..." << endl;

      		        orb->register_value_factory("IDL:Quiz/Answer:1.0", new Quiz::Answer_init());

                        create_questions();         
                
                        //
                        // get random question
                        //
                        orb->register_value_factory("IDL:Quiz/Question:1.0", new Quiz::Question_init());

                        Quiz::Question* received_question = new OBV_Quiz::Question();
                        service_server->getQuestion(received_question);
                        const char* received_question_sentence = received_question->sentence();
                        CORBA::Long received_question_id = received_question->id();
                        Quiz::Question::AnswerSeq received_question_answers = received_question->answers();               
                        int numAnswers = received_question_answers.length();

                        cout << "Received Question: id=" << received_question_id << ", sentence=" << received_question_sentence << endl;
                        
                        for(int i = 0; i < numAnswers; i++) { 
                            if(received_question_answers[i]) {
                                cout << "\t" << received_question_answers[i]->id() << ": " << received_question_answers[i]->sentence() << endl;
                            }
                        }
		}

		//------------------------------------------------------------------------
		// Destroy OBR
   		//------------------------------------------------------------------------
		orb->destroy();

	} catch (CORBA::UNKNOWN) {
		cerr << "Caught CORBA exception: unknown exception" << endl;
	}
}


void insert_question(const char* sentence, int numAnswers, Quiz::Answer** answers, int numCorrectAnswers, CORBA::Char* correctAnswers)
{
        Quiz::Question::AnswerSeq* answersSeq = new OBV_Quiz::Question::AnswerSeq(numAnswers, numAnswers, answers, 1);                
        Quiz::CompleteQuestion::CharSeq* correctAnswersSeq = new OBV_Quiz::CompleteQuestion::CharSeq(numCorrectAnswers, numCorrectAnswers, correctAnswers, 1);
        Quiz::CompleteQuestion* new_question = new OBV_Quiz::CompleteQuestion(0, sentence, *answersSeq, *correctAnswersSeq);

	CORBA::Long question_received_id = service_server->insertQuestion(new_question);
        cout << "send question and received id " << question_received_id << endl;    
}

void create_questions()
{
	// create first question
        const char* question_sentence = "It applies to a software layer that provides a programming abstraction as well as masking the heterogeneity of the underlying networks, hardware, operating systems and programming languages. What is it?";                
        Quiz::Answer** question0_answers = new Quiz::Answer*[3];
        question0_answers[0] = new OBV_Quiz::Answer('a', "Hetereogenity");
        question0_answers[1] = new OBV_Quiz::Answer('b', "Middleware");
        question0_answers[2] = new OBV_Quiz::Answer('c', "Opennes");
        CORBA::Char question0_correctAnswers[] = {'b'};
        insert_question(question_sentence, 3, question0_answers, 1, question0_correctAnswers);
            
        // create second question
        question_sentence = "It refers to a running program (a process) on a networked computer that accepts requests from programs running on other computers to perform a service and responds appropriately.";
        Quiz::Answer** question1_answers = new Quiz::Answer*[3];
        question1_answers[0] = new OBV_Quiz::Answer('a', "Server");
        question1_answers[1] = new OBV_Quiz::Answer('b', "Middleware");
        question1_answers[2] = new OBV_Quiz::Answer('c', "Client");
        CORBA::Char question1_correctAnswers[] = {'a'};
        insert_question(question_sentence, 3, question1_answers, 1, question1_correctAnswers);    
}

Run code

Build and compile

Go to the java folder, use first the idlj compiler and then the Java compiler (to compile all .java files)

cd java
idlj - fall ../Quiz.idl
javac */*.java

Got to the cpp folder and run the Makefile

cd cpp
make

Makefile for C++ client

cpp/Makefile

CC            = /usr/bin/g++
CPPFLAGS      = -g -c
LDFLAGS       = -g
OMNI_HOME     = /usr
OMNI_INCLUDES = -I$(OMNI_HOME)/include
OMNI_LIB_DIR  = $(OMNI_HOME)/lib
OMNIIDL       = omniidl
INCLUDES      = $(OMNI_INCLUDES)
LIBS          = -lomniORB4 -lomnithread -lomniDynamic4
OBJECTS       = QuizSK.o client.o

client: $(OBJECTS)
	$(CC) $(LDFLAGS) -o client $(OBJECTS) $(LIBS)

client.o: client.cpp
	$(CC) $(CPPFLAGS) client.cpp

QuizSK.o: QuizSK.cc
	$(CC) $(CPPFLAGS) QuizSK.cc

QuizSK.cc: ../Quiz.idl
	$(OMNIIDL) -bcxx ../Quiz.idl

clean:
	rm -rf *.o
	rm -rf *.hh
	rm -rf *SK.cc
	rm -rf client

Execute

Start omniNames services

sudo omniNames -start 4333

Use the run bash file to start the server and several clients:

bash run server

In a new terminal

bash run client
bash run interactive-client

run bash file

#!/bin/bash
BASEDIR=`dirname $0`
 
if [ "$#" -lt 1 ]
then
	echo "Usage $0 [server|interactive-client|client]"
	echo "Example: bash $0 server"
	echo
	echo "server: start Java server"
	echo "interactive-client: start Java interactive-client"
	echo "client: start C++ client"
	exit 1
fi

case "$1" in
"server")
	cd java
	java server.QuizServer -ORBInitRef NameService=corbaloc::localhost:4333/NameService
	;;
"interactive-client")
	cd java
	java client.QuizClientInteractive -ORBInitRef NameService=corbaloc::localhost:4333/NameService
	;;
"client")
	cd cpp
	./client -ORBInitRef NameService=corbaloc::localhost:4333/NameService
esac

Output

Example output for one server and two client.

Server

user@pc:~/My_CORBA_project$ bash run server
QuizServer ready and waiting ...
> receive new question CompleteQuestionImpl [correctAnswers=[b], id=0, sentence=It applies to a software layer that provides a programming abstraction as well as masking the heterogeneity of the underlying networks, hardware, operating systems and programming languages. What is it?, answers=[AnswerImpl [id=a, sentence=Hetereogenity], AnswerImpl [id=b, sentence=Middleware], AnswerImpl [id=c, sentence=Opennes]]]
send question id: 0
> receive new question CompleteQuestionImpl [correctAnswers=[a], id=0, sentence=It refers to a running program (a process) on a networked computer that accepts requests from programs running on other computers to perform a service and responds appropriately., answers=[AnswerImpl [id=a, sentence=Server], AnswerImpl [id=b, sentence=Middleware], AnswerImpl [id=c, sentence=Client]]]
send question id: 1
> receive random question request
send question: QuestionImpl [id=0, sentence=It applies to a software layer that provides a programming abstraction as well as masking the heterogeneity of the underlying networks, hardware, operating systems and programming languages. What is it?, answers=[AnswerImpl [id=a, sentence=Hetereogenity], AnswerImpl [id=b, sentence=Middleware], AnswerImpl [id=c, sentence=Opennes]]]
> receive random question request
send question: QuestionImpl [id=0, sentence=It applies to a software layer that provides a programming abstraction as well as masking the heterogeneity of the underlying networks, hardware, operating systems and programming languages. What is it?, answers=[AnswerImpl [id=a, sentence=Hetereogenity], AnswerImpl [id=b, sentence=Middleware], AnswerImpl [id=c, sentence=Opennes]]]
> receive new question CompleteQuestionImpl [correctAnswers=[A], id=0, sentence=My question is ...?, answers=[AnswerImpl [id=A, sentence=My first answer.], AnswerImpl [id=B, sentence=My seconds answer.]]]
send question id: 2

Non-interactive C++ client

user@pc:~/My_CORBA_project$ bash run client
QuizClient client is running ...
send question and received id 0
send question and received id 1
Received Question: id=0, sentence=It applies to a software layer that provides a programming abstraction as well as masking the heterogeneity of the underlying networks, hardware, operating systems and programming languages. What is it?
	a: Hetereogenity
	b: Middleware
	c: Opennes
user@pc:~/My_CORBA_project

Interactive Java client

user@pc:~/My_CORBA_project$ bash run interactive-client
Welcome to the Quiz Client.

------ Please choose an option:
a: Insert a new question
b: Request a random question
c: Remove a question
b
------ Request Question
The question is: It applies to a software layer that provides a programming abstraction as well as masking the heterogeneity of the underlying networks, hardware, operating systems and programming languages. What is it?
a: Hetereogenity
b: Middleware
c: Opennes
Which is the correct answer? Write the letters followed by a comma (,) in order if there are more than one correct answer
a,c
You're wrong, I'm sorry! These are the correct answers:
b
Would you like to do somenthing else? Y or N
y

------ Please choose an option:
a: Insert a new question
b: Request a random question
c: Remove a question
a
------ Insert your new question:
My question is ...?
How many alternative would you like to insert? 
2
How many alternative are correct? 
1
Write your alternative! 
My first answer.    
Is it correct? Y or N 
y
Write your alternative! 
My seconds answer.
> reseived question id: 2
Would you like to do somenthing else? Y or N
n
Goodbye. Quit.
user@pc:~/My_CORBA_project$

See also