Skip to content

Commit

Permalink
Fixed multiple clients parallel access issue, created separate packag…
Browse files Browse the repository at this point in the history
…e for exceptions
  • Loading branch information
prat-man committed Nov 15, 2019
1 parent f42ade6 commit 33d1359
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 40 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>tk.pratanumandal</groupId>
<artifactId>unique4j</artifactId>
<version>1.0</version>
<version>1.1</version>
<packaging>jar</packaging>

<name>Unique4j</name>
Expand Down
92 changes: 56 additions & 36 deletions src/main/java/tk/pratanumandal/unique4j/Unique.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

import tk.pratanumandal.unique4j.exception.Unique4jException;

/**
* The <code>Unique</code> class is the logical entry point to the library.<br>
* It allows to create an application lock or free it and send and receive messages between first and subsequent instances.<br><br>
Expand Down Expand Up @@ -92,10 +94,10 @@ public abstract class Unique {
private static final String TEMP_DIR = System.getProperty("java.io.tmpdir");

/**
* Unique string representing the application ID.
* Unique string representing the application ID.<br><br>
*
* The APP_ID must be as unique as possible.
* Avoid generic names like "my_app_id" or "hello_world".
* Avoid generic names like "my_app_id" or "hello_world".<br>
* A good strategy is to use the entire package name (group ID + artifact ID) along with some random characters.
*/
public final String APP_ID;
Expand All @@ -113,10 +115,10 @@ public abstract class Unique {
private FileLock fileLock;

/**
* Parameterized constructor.
* Parameterized constructor.<br><br>
*
* The APP_ID must be as unique as possible.
* Avoid generic names like "my_app_id" or "hello_world".
* Avoid generic names like "my_app_id" or "hello_world".<br>
* A good strategy is to use the entire package name (group ID + artifact ID) along with some random characters.
*
* @param APP_ID Unique string representing the application ID
Expand Down Expand Up @@ -170,34 +172,47 @@ public void run() {
while (!server.isClosed()) {
try {
// establish connection
Socket socket = server.accept();

// open writer
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os, true);

// open reader
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

// read message from client
String message = br.readLine();
if (message == null) message = new String();

// write response to client
pw.write(APP_ID + "\r\n");
pw.flush();

// close writer and reader
pw.close();
br.close();
final Socket socket = server.accept();

// perform user action on message
receiveMessage(message);
// handle socket on a different thread to allow parallel connections
Thread thread = new Thread() {
@Override
public void run() {
try {
// open writer
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os, true);

// open reader
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

// read message from client
String message = br.readLine();
if (message == null) message = new String();

// write response to client
pw.write(APP_ID + "\r\n");
pw.flush();

// close writer and reader
pw.close();
br.close();

// perform user action on message
receiveMessage(message);

// close socket
socket.close();
} catch (IOException e) {
handleException(new Unique4jException(e));
}
}
};

// close socket
socket.close();
// start socket thread
thread.start();
} catch (SocketException e) {
if (!server.isClosed()) {
handleException(new Unique4jException(e));
Expand Down Expand Up @@ -331,7 +346,10 @@ private void lockFile(int port) throws Unique4jException {
try {
lockRAF = new RandomAccessFile(file, "rw");
FileChannel fc = lockRAF.getChannel();
fileLock = fc.lock(0, Long.MAX_VALUE, true);
fileLock = fc.tryLock(0, Long.MAX_VALUE, true);
if (fileLock == null) {
throw new Unique4jException("Failed to obtain file lock");
}
} catch (FileNotFoundException e) {
throw new Unique4jException(e);
} catch (IOException e) {
Expand Down Expand Up @@ -375,23 +393,25 @@ public void free() throws Unique4jException {
}

/**
* Method used in first instance to receive messages from subsequent instances.
* Method used in first instance to receive messages from subsequent instances.<br>
* This method is not synchronized.
*
* @param message message received by first instance from subsequent instances
*/
public abstract void receiveMessage(String message);

/**
* Method used in subsequent instances to send message to first instance.
* Method used in subsequent instances to send message to first instance.<br>
* This method is not synchronized.
*
* @return message sent from subsequent instances
*/
public abstract String sendMessage();

/**
* Method to receive and handle exceptions occurring while first instance is listening for subsequent instances.
*
* By default prints stack trace of all exceptions. Override this method to change handle explicitly.
* Method to receive and handle exceptions occurring while first instance is listening for subsequent instances.<br>
* By default prints stack trace of all exceptions. Override this method to change handle explicitly.<br>
* This method is not synchronized.
*
* @param exception exception occurring while first instance is listening for subsequent instances
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
*
*/

package tk.pratanumandal.unique4j;
package tk.pratanumandal.unique4j.exception;

/**
* The <code>Unique4jException</code> class is a wrapper for all exceptions thrown from Unique4j.
*
* @author Pratanu Mandal
* @since 1.0
* @since 1.1
*
*/
public class Unique4jException extends Exception {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright 2019 Pratanu Mandal
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

/**
* The <code>tk.pratanumandal.unique4j.exception</code> package contains exception classes of Unique4j library.
*
* @author Pratanu Mandal
* @since 1.1
*
*/
package tk.pratanumandal.unique4j.exception;
2 changes: 1 addition & 1 deletion src/main/java/tk/pratanumandal/unique4j/package-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

/**
* The <code>tk.pratanumandal.unique4j</code> package is the root package of unique4j library.
* The <code>tk.pratanumandal.unique4j</code> package is the root package of Unique4j library.
*
* @author Pratanu Mandal
* @since 1.0
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/tk/pratanumandal/unique4j/Unique4jTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import org.junit.Test;

import tk.pratanumandal.unique4j.exception.Unique4jException;

public class Unique4jTest {

@Test
Expand Down

0 comments on commit 33d1359

Please sign in to comment.