Upgrade details

Fixed bugs


New functionalities


API modifications

Unfortunately there is no backward compatibility from the version 2.0 to 3.0 !

Indeed several points of the API must have been partially or completely changed so that having the new functionalities listed above. In the most cases it only implies simplifications of the manner you are using this library. You may have some upgrade problems especially if you have customized your UWS while using the version 2.

That's why, the most important API modifications are listed and explained below. Besides I encourage you to take a look at the UML class diagrams of the two versions (v2.0 and v3.0), to have a better view of the main differences between these versions and to find the best way to do what you want more easily.

1. Servlet

a. User identification

With the version 2, to have the notion of user, the UWS was encapsulated in a session. The problem with this solution is that the servlet has to manage one UWS object per session and so per web-navigator interacting with the server. Thus we have not really one web service for several users, but one web-service per user. In addition this solution doesn't really identify a user, but one client (in the most cases, a web-navigator).

For those reasons, it would be better to replace this pseudo user identification by a true one. The interface UserIdentifier of the version 3 of this library is fully dedicated to this task. Once implemented, its only function is called by your UWS at each received request.

For more details see D.3. User identification.

b. HTTP methods

With the version 3 of this library, the servlet may be now very simple ! Indeed, the method init(ServletConfig) of HttpServlet is now used to create a UWS, whereas the method service(HttpServletRequest, HttpServletResponse) only forwards the request to the UWS. It is not required any more to forward request with doGet, doPost, doPut and doDelete as it was explained in the tutorial of the version 2. Actually it would rather be discouraged to forward request like that, because AbstractUWS is now designed to interpret request whatever is the used HTTP method.

For more information about the way a UWS servlet may be written, see the part A.2. Writing the servlet. In this part a servlate template can also be downloaded.

Version 2.0

	public class UWSTimers extends HttpServlet {
		private static final long serialVersionUID = 1L;
	
		@Override
		protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			doPost(req, resp);
		}
	
		@Override
		protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			doPost(req, resp);
		}
	
		@Override
		protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			doPost(req, resp);
		}
	
		@SuppressWarnings("unchecked")
		@Override
		protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			try{
				// Get the current session (or create a new one):
				HttpSession session = req.getSession(true);
				
				/* If it is a new session, set its maximum inactive time interval ;
				*  so that all managed jobs lists can be removed and so all jobs stopped (if running) and their resources freed
				*  once the given time interval elapsed */
	//			if (session.isNew())
	//				session.setMaxInactiveInterval(3600);
	
				// Fetch the UWS from the current session:
				BasicUWS<JobChrono> uws = (BasicUWS<JobChrono>)session.getAttribute("BasicUWS");
				
				// INITIALIZE OUR UWS:
				if (uws == null){
					// Get the base UWS URL:
					URL baseUWSUrl = UWSUrl.extractBaseUWSUrl(req, true);
					
					// Create our UWS:
					uws = new BasicUWS<JobChrono>(baseUWSUrl, JobChrono.class);
					uws.setDescription("This UWS aims to manage one (or more) JobList(s) of JobChrono." +
										"JobChrono is a kind of Job whose the execution task consists to wait a given time.");
					
					// Create our job list:
					uws.addJobList(new JobList<JobChrono>("timers", uws.getBaseURL()));
					
					// Add this UWS to the current session:
					session.setAttribute("BasicUWS", uws);
				}
				
				// FORWARD THE REQUEST TO THE UWS:
				boolean done = uws.executeRequest(req, resp);
				
				System.out.println("### UWS INFO : REQUEST ? "+(done?"OK":"NOT DONE")+" ###");
					
			}catch(UWSException uwsEx){
				// Display properly the caught UWSException:
				resp.sendError(uwsEx.getHttpErrorCode(), uwsEx.getMessage());
				
			}catch(MalformedURLException mue){
				System.err.println("### UWS ERROR : wrong base UWS URL ! ###");
				throw new ServletException(mue);
			}
		}
		
	}

Version 3.0

	public class UWSTimers extends HttpServlet {
		private static final long serialVersionUID = 1L;
		
		protected BasicUWS<JobChrono> uws = null;
	
		@SuppressWarnings("unchecked")
		@Override
		public void init(ServletConfig config) throws ServletException {
			super.init(config);
			
			// INITIALIZE OUR UWS:
			try{
				// Create the UWS:
				uws = new BasicUWS<JobChrono>(JobChrono.class);
				
				// Set the way the UWS must identify a user:
				uws.setUserIdentifier(new UserIdentifier() {
					private static final long serialVersionUID = 1L;
	
					@Override
					public String extractUserId(UWSUrl urlInterpreter, HttpServletRequest request) throws UWSException {
						return request.getRemoteAddr();
					}
				});
				
				// Set a description:
				uws.setDescription("This UWS aims to manage one (or more) JobList(s) of JobChrono." +
									"JobChrono is a kind of Job whose the execution task consists to wait a given time");
				
				// Create the job list "timers":
				uws.addJobList(new JobList<JobChrono>("timers"));
			}catch(UWSException ex){
				throw new ServletException(ex);
			}
		}
	
		@Override
		protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			try{
				// FORWARD THE REQUEST TO THE UWS:
				boolean done = uws.executeRequest(req, resp);
				
				System.out.println("### UWS INFO : REQUEST ? "+(done?"OK":"NOT DONE")+" ###");
				
			}catch(UWSException uwsEx){
				// Display properly the caught UWSException:
				resp.sendError(uwsEx.getHttpErrorCode(), uwsEx.getMessage());
			}
		}
		
	}

2. UWS

a. UWS Actions

In the previous version you were able to customize all the default UWS actions by overriding the corresponding functions in AbstractUWS: listJobs(JL, javax.servlet.http.HttpServletResponse), addJob(JL, Map<String,String>, HttpServletResponse), jobSummary(J, HttpServletResponse), ..... So that allowing to add and to remove UWS actions, all these methods have been replaced by an instance of UWSAction in v3.0:

v2.0 v3.0
writeHomePage(HttpServletResponse) ShowHomePage
listJobs(JL, HttpServletResponse) ListJobs
addJob(JL, Map<String,String>, HttpServletResponse) AddJob
jobSummary(J, HttpServletResponse) JobSummary
destroyJob(JL, J, HttpServletRequest, HttpServletResponse) DestroyJob
getJobParam(J, String, HttpServletResponse) GetJobParam
setJobParam(JL, J, String, HttpServletResponse) SetJobParam

Consequently, the done customizations must be moved into extensions of the corresponding UWSAction implementations. Then you just have to substitute the default actions in your UWS.

Version 2.0

public class MyUWS extends BasicUWS<JobChrono> {
	...
	@Override
	public void listJobs(JobList<JobChrono> jl, HttpServletResponse response) throws UWSException, java.io.IOException {
		System.out.println("Hello ! I am printing the jobs list "+jl.getName()+" !");
		super.listJobs(jl, response);
	}
	...
}

Version 3.0

myUws.replaceUWSAction(new MyListJob<JobList<JobChrono>, JobChrono>(myUws));
					
public class MyListJob<JL extends JobList<J>, J extends AbstractJob> extends ListJobs<JL, J> {
	...
	@Override
	public boolean apply(UWSUrl url, String userId, HttpServletRequest request, HttpServletResponse response) throws UWSException, IOException {
		System.out.println("Hello ! "+userId+" is printing the jobs list "+url.getJobListName()+" !");
		super.apply(url, userId, request, response);
	}
	...
}

See D.6. Actions for more details about the UWS action customization.

b. Action identification

The class UWSParameters does not exist any more in the version 3.0. It was used to interpret the URL so that identifying the corresponding action. But now, each action is able to indicate whether it can be applied or not, considering a given HTTP request. Consequently, the interpretation of the URL has been moved directly into the method executeRequest(HttpServletRequest, HttpServletResponse). Then this method loops on the list of all available actions and executes the first one which matches with the given HTTP request.

If you had customized UWSParameters, you have two cases. If your modifications concern:

c. URL interpretation

Even if UWSUrl still exists, it has been subject to many modifications:

All these modifications and some others are explained in more details in the part D.5. UWS URL interpretation. Instructions about the way to customize UWSUrl are also given.

3. Job