java.net.SocketException: Broken pipe smpp.logica library - java

why i got this error
20:43:40,798 ERROR Tx:809 - java.net.SocketException: Broken pipe
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:109)
at com.logica.smpp.TCPIPConnection.send(TCPIPConnection.java:353)
at com.logica.smpp.Transmitter.send(Transmitter.java:79)
at com.logica.smpp.Session.send(Session.java:993)
at com.logica.smpp.Session.send(Session.java:1048)
at com.logica.smpp.Session.enquireLink(Session.java:789)
at com.logica.smpp.Tx.kirimEnquireLink(Tx.java:795)
at com.logica.smpp.Tx.access$0(Tx.java:777)
at com.logica.smpp.Tx$1.run(Tx.java:120)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
..I'm Using Open smpp logica library to create smsc client..for a few hours it's work but then the error come out..when i'm trying to send enquiry link,,the session I create is syncronize and the type of connection is Transceiver here's a piece of code i used to bind and to enqury link
private void bind()
{
debug.enter(this, "SMPPTest.bind()");
try {
if (bound) {
System.out.println("Already bound, unbind first.");
return;
}
BindRequest request = null;
BindResponse response = null;
String syncMode = (asynchronous ? "a" : "s");
// type of the session
syncMode = getParam("Asynchronous/Synchronnous Session? (a/s)",
syncMode);
if (syncMode.compareToIgnoreCase("a")==0) {
asynchronous = true;
} else if (syncMode.compareToIgnoreCase("s")==0) {
asynchronous = false;
} else {
System.out.println("Invalid mode async/sync, expected a or s, got "
+ syncMode +". Operation canceled.");
return;
}
// input values
bindOption = getParam("Transmitter/Receiver/Transciever (t/r/tr)",
bindOption);
if (bindOption.compareToIgnoreCase("t")==0) {
request = new BindTransmitter();
} else if (bindOption.compareToIgnoreCase("r")==0) {
request = new BindReceiver();
} else if (bindOption.compareToIgnoreCase("tr")==0) {
request = new BindTransciever();
} else {
System.out.println("Invalid bind mode, expected t, r or tr, got " +
bindOption + ". Operation canceled.");
return;
}
ipAddress = getParam("IP address of SMSC", ipAddress);
port = getParam("Port number", port);
TCPIPConnection connection = new TCPIPConnection(ipAddress, port);
connection.setReceiveTimeout(20*1000);
session = new Session(connection);
systemId = getParam("Your system ID", systemId);
password = getParam("Your password", password);
// set values
request.setSystemId(systemId);
request.setPassword(password);
request.setSystemType(systemType);
request.setInterfaceVersion((byte)0x34);
request.setAddressRange(addressRange);
// send the request
System.out.println("Bind request " + request.debugString());
if (asynchronous) {
pduListener = new SMPPTestPDUEventListener(session);
response = session.bind(request,pduListener);
} else {
response = session.bind(request);
}
System.out.println("Bind response " + response.debugString());
if (response.getCommandStatus() == Data.ESME_ROK) {
System.out.println("CommandID "+response.getCommandId());
bound = true;
}
} catch (Exception e) {
event.write(e,"");
debug.write("Bind operation failed. " + e);
System.out.println("Bind operation failed. " + e);
} finally {
debug.exit(this);
}
}
the code for enquiry link is
private void kirimEnquireLink()
{
try
{
log.info("Send enquireLink!");
EnquireLink request = new EnquireLink();
EnquireLinkResp response = new EnquireLinkResp();
// synchronized (session) {
// session.enquireLink(request);
// }
if(asynchronous)
{
session.enquireLink(request);
}else
{
response = session.enquireLink(request);
System.out.println("Enquire Link Response "+request.debugString());
}
}
catch (Exception e)
{
bound = false;
// unbind();
log.error(e, e);
}
}
i called enquiry link every 10 second,, any idea why

The problem you are facing is that there is never insurance that connection will be always available, nor the session. Many different external reasons can bring the link between ESME and SMSC down. My suggestion, try-catch the enquire_link operations and the submit operations, evaluate the Exception and take action.
I've successfully implemented recursive method calls to deal with this issue as follows
/**
* Connect to ESME and submit a message, if binding process fails, reattempt
* to reconnect and submit.
*/
public void connect() {
try {
//Create connection
BindRequest request = null;
request = new BindTransciever();
connection = new TCPIPConnection("localhost", 17632);
connection.setReceiveTimeout(20 * 1000);
session = new Session(connection);
//Prepare request
request.setSystemId("pavel");
request.setPassword("wpsd");
request.setSystemType("CMT");
request.setInterfaceVersion((byte) 0x34);
request.setAddressRange(new AddressRange());
pduListener = new SMPPTestPDUEventListener(session);
//Session binding process, if it fails, we are thrown to the catch section
//with a BrokenPipe (IOException)
session.bind(request, pduListener);
//Prepare message
SubmitSM msg = new SubmitSM();
// set values
msg.setDestAddr("04234143939");
msg.setShortMessage("hello");
msg.assignSequenceNumber(true);
//Send to our custom made submitMessage method that reattempts if failure
submitMessage(msg);
} catch (Exception ex){
//Analyze what type of exception was
if (ex instanceof IOException || ex instanceof SocketException){
//IOException relate to the brokenpipe issue you are facing
//you need to close existing sessions and connections
//restablish session
if (this.connection!=null){
this.connection.close();
}
//This is a recursive call, I encourage you to elaborate
//a little bit this method implementing a counter so you
//don't end up in an infinite loop
this.connect();
} else {
//LOG whatever other exception thrown
}
}
}
/**
* Submit message to SMSC, if it fails because of a connection issue, reattempt
* #param message
*/
private void submitMessage(SubmitSM message){
try{
session.submit(message);
} catch (Exception ex){
//Analyze what type of exception was
if (ex instanceof IOException || ex instanceof SocketException){
//IOException relate to the brokenpipe issue you are facing
//you need to close existing sessions and connections
//restablish session and try to submit again
if (this.connection!=null){
this.connection.close();
}
//Call a rebind method
this.bind();
//This is a recursive call, I encourage you to elaborate
//a little bit this method implementing a counter so you
//don't end up in an infinite loop
this.submitMessage(message);
} else {
//LOG whatever other exception thrown
}
}
}
Do the same with the enquire_link, try-catch, during IOException rebind, and reattempt. Do not forget to add a couter and a maximum ammount of attempts in order to avoid infinite loops during recursive calls.
You do not need to enquire_link every 10 seconds. Most providers will let you know how often it needs to be done, the standard is 10 minutes.

Related

how to init snmp V3 Parameters to get snmpV3 trap using AdventNet

I am trying to recieve SNMP v3 traps from a device, using Adventnet.
When getting a trap I see the following AdventNet exception thrown:
Exception while constructing message after receiving PDU. Dropping this PDU received from xxx.xxx.xxx.xxx. com.adventnet.snmp.snmp2.SnmpException: Parse Header: Incorrect Scoped data
If I monitor the traps using NG-Soft browser the traps are recieved correctly.
Here is my code:
private void initV3Parameters(NEData neData) throws InterruptedException
{
logger.debug("in.");
try
{
logger.debug(".in");
SnmpAPI m_api = new SnmpAPI();
m_api.setDebug( true );
SnmpSession m_session = new SnmpSession(m_api);
m_session.addSnmpClient(this);
UDPProtocolOptions m_udpOpt = new UDPProtocolOptions();
m_udpOpt.setRemoteHost(neData.m_szIpAddress);
m_session.setProtocolOptions(m_udpOpt);
try
{
m_session.open();
String message="Succes to bind port: "+session.getLocalPort();
logger.info(message);
System.out.println(message);
}
catch (Exception ex)
{
String message = "Failed to open session - Port in use or permission denied. \n Message- "+ ex.getMessage() + "\n Will exit from Trap process. ";
logger.error(message, ex);
System.err.println(message);
throw new RuntimeException(message);
}
SnmpEngineEntry engineentry = new SnmpEngineEntry(neData.m_szIpAddress, m_udpOpt.getRemotePort());
SnmpEngineTable enginetable = m_api.getSnmpEngine();
enginetable.addEntry(engineentry);
try
{
engineentry.discoverSnmpEngineID(m_session,10000,3);
}
catch (Exception e)
{
logger.error("Failed to discover snmp EngineID. " + e.getMessage());
printToLog("failed",neData);
return;
}
USMUserEntry entry = new USMUserEntry(neData.usmUser.getBytes(), engineentry.getEngineID());
entry.setAuthProtocol(Integer.parseInt(neData.authProtocol));
entry.setAuthPassword(neData.authPassword.getBytes());
entry.setPrivProtocol(Integer.parseInt(neData.privProtocol));
entry.setPrivPassword(neData.privPassword.getBytes());
byte[] authKey = USMUtils.password_to_key(entry.getAuthProtocol(),
neData.authPassword.getBytes(),
neData.authPassword.getBytes().length,
engineentry.getEngineID());
entry.setAuthKey(authKey);
byte[] privKey = USMUtils.password_to_key(entry.getAuthProtocol(),
neData.privPassword.getBytes(),
neData.privPassword.getBytes().length,
engineentry.getEngineID());
entry.setPrivKey(privKey);
entry.setEngineEntry(engineentry);
entry.setSecurityLevel(Snmp3Message.AUTH_PRIV);
SecurityProvider provider = m_api.getSecurityProvider();
USMUserTable userTable = (USMUserTable) provider.getTable(3);
userTable.addEntry(entry);
entry.timeSynchronize(m_session, m_udpOpt);
printToLog("success",neData);
}
catch (Exception exp)
{
logger.error(exp.getMessage()+" for ip = "+neData.m_szIpAddress,exp);
discoveredDeque.put(neData);
printToLog("failed",neData);
}
}
I've also tried Using High-Level API
USMUtils.init_v3_parameters(
neData.usmUser,
null,
Integer.valueOf(neData.authProtocol),
neData.authPassword,
neData.privPassword,
udpOptions,
session,
false,
Integer.valueOf(neData.privProtocol));
In this case I see the trap using public void debugPrint (String debugOutput)
and no exception is throwing.
But there is nothing in the callback
Any advice will be welcome!!!
It turns out that there was a problem with the time synchronization of the device that sends the traps and my code worked perfectly fine.
probably NG-Soft doesn't care from time sync...
I attach my code here in case any of you will need it in the future...
private SnmpSession session;
/**
* Create a listener for trap version 1-2
*/
public void trapsListener ()
{
logger.debug(".in");
SnmpAPI api = new SnmpAPI();
// api.setDebug( true );
session = new SnmpSession(api);
session.addSnmpClient(this);
UDPProtocolOptions udpOpt = new UDPProtocolOptions();
udpOpt.setLocalPort(TRAP_PORT);
session.setProtocolOptions(udpOpt);
try
{
session.open();
String message="Succes to bind port: "+session.getLocalPort();
logger.info(message);
System.out.println(message);
}
catch (Exception ex)
{
String message = "Failed to open session - Port in use or permission denied. \n Message- "+ ex.getMessage() + "\n Will exit from Trap process. ";
logger.error(message, ex);
System.err.println(message);
throw new RuntimeException(message);
}
}
/**
* For each new device
* 1) discover the snmp engineID
* 2) create SnmpEngineEntry and add it to SnmpEngineTable
* 3) create USMUserEntry and add it to USMUserTable
* 4) performs time synchronization
**/
private void initV3Parameters(Device data) throws InterruptedException
{
logger.debug("in.");
try
{
UDPProtocolOptions udpOptions = new UDPProtocolOptions();
udpOptions.setLocalPort(TRAP_PORT);
udpOptions.setRemoteHost(data.getIpAddress());
USMUtils.init_v3_parameters(
data.getUsmUser(),
null,// null means that the SNMPv3 discovery will be activated
Integer.valueOf(data.getAuthProtocol()),
data.getAuthPassword(),
data.getPrivPassword(),
udpOptions,
session,
false,
Integer.valueOf(data.getPrivProtocol()));
printToLog("secsses",data);
}
catch (SnmpException exp) {
logger.error(exp.getMessage()+" for ip = "+data.getIpAddress(),exp);
printToLog("failed",data);
}
}

how to receive snmpv3 trap with AdventNet

I'm trying to add the option to get a TRAP V3 (I can get TRAP V1 and V2).
here is the Session init
public void CreateSession()
{
logger.debug(".in");
System.out.println("Waiting to receive traps .......");
api = new SnmpAPI();
api.setDebug( true );
session = new SnmpSession(api);
session.addSnmpClient(this);
udpOpt = new UDPProtocolOptions();
udpOpt.setLocalPort(TRAP_PORT);
session.setProtocolOptions(udpOpt);
try
{
session.open();
String message="Succes to bind port: "+session.getLocalPort();
logger.info(message);
System.out.println(message);
}
catch (Exception ex)
{
String message = "Failed to open session - Port in use or permission denied. \n Message- "+ ex.getMessage() + "\n Will exit from Trap process. ";
logger.error(message, ex);
System.err.println(message);
throw new RuntimeException(message);
}
}
Every time I set up a device in V3 I perform the discovery and its registration to the tables using the method USMUtils.init_v3_parameters.
private void initV3Parameters(NEData neData) throws InterruptedException
{
logger.debug("in.");
try
{
UDPProtocolOptions udpOptions = new UDPProtocolOptions();
udpOptions.setLocalPort(TRAP_PORT);
udpOptions.setRemoteHost(neData.m_szIpAddress);
USMUtils.init_v3_parameters(
neData.usmUser,
null,
Integer.valueOf(neData.authProtocol),
neData.authPassword,
neData.privPassword,
udpOptions,
session,
false,
Integer.valueOf(neData.privProtocol));
printToLog("success",neData);
}
catch (SnmpException exp) {
logger.error(exp.getMessage()+" for ip = "+neData.m_szIpAddress,exp);
discoveredDeque.put(neData);
printToLog("failed",neData);
}
}
When TRAP V1 or V2 arrives it comes to this function and it works perfect.But I want to add the V3 as well
/**
* Receives incoming PDUs and adds them to the traps queue. Notifies the
* internal thread on the arrival of each PDU.
*/
public boolean callback (SnmpSession session, SnmpPDU pdu, int requestID)
{
logger.info("in session= "+session+" ,pdu= "+pdu+" ,requestID = "+requestID);
if (pdu == null)
{
logger.info("Received null PDU");
}
else
{
// Add the PDU to the end of the traps queue.
// Notify the internal thread.
try
{
synchronized (this)
{
Object t = m_Traps.addElement(pdu);
if (t != null)
{
// The new trap replaced an old one.
logger.info("Queue full: replaced old PDU");
}
notify();
}
}
catch (Exception ex)
{
logger.error(ex.getMessage(),ex);
}
}
// All PDUs are handled, so true should always be returned.
return true;
}
I have debugPrint implementation from SnmpClient and it seems that AdventNet gets the TRAP but does not do anything with it...
The SNMP agent is implemented using NetSNMP.
What is missing to make AdventNet handle the V3 TRAP?
Is this the right callback function to use?
public boolean callback (SnmpSession session, SnmpPDU pdu, int requestID)

Connection close in Java Servlet and SSE

I try to implement Server-Sent-Event in my Webapp with Java Serlvet on server.
Is it possible to check in Servlet that connection is closed by client? The loop while(true) in Servlet is infinite even if client browser is closed.
Client code
function startLogSSE(lastEventId, level) {
var eventSource = new EventSource("log-sse?last-event-id=" + lastEventId + "&level=" + level);
eventSource.onmessage = function (event) {
document.getElementById('log').innerHTML = event.data + "\n" + document.getElementById('log').innerHTML;
};
}
Server code
public class LogSSEServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(LogSSEServlet.class);
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/event-stream");
response.setCharacterEncoding("UTF-8");
PrintWriter writer = response.getWriter();
// get logger purgerDB appender
PurgerDBAppender appender = LogUtils.getPurgerDBAppender();
if (appender == null) {
writer.write("data: [ERROR] Appender 'purgerDB' isn't found for logger 'com.bp3'\n\n");
writer.close();
return;
}
int eventId = 0;
// get last-event-id
String lastEventId = request.getHeader("last-event-id");
if (lastEventId == null) {
// try to get lastEventId from parameter
lastEventId = request.getParameter("last-event-id");
}
if (lastEventId != null) {
try {
eventId = Integer.parseInt(lastEventId);
} catch (NumberFormatException e) {
logger.error("Failed to parse last-event-id: " + lastEventId);
}
}
String minLevel = request.getParameter("level");
if (minLevel == null) {
minLevel = "TRACE";
}
// get logs from purgerDB logger appender
LogServices logServices = new LogServices();
try {
logServices.open();
} catch (SQLException e) {
throw new ServletException(e);
}
try {
while (true) {
List<LogMessage> messages = logServices.getLastMessages(Level.toLevel(minLevel), eventId, 0);
if (messages.size() > 0) {
writer.write("id: " + messages.get(0).getEventId() + "\n");
writer.write("data: " + LogUtils.formatLog(messages) + "\n");
writer.flush();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
} catch (SQLException e) {
throw new ServletException(e);
} finally {
logServices.closeQuietly();
}
}
}
Is it possible to check in Servlet that connection is closed by client?
Eventually an exception will be thrown: either an IOException: connection reset if you are streaming directly to the socket, or an OutOfMemoryError if the container is streaming to memory, which it does when you aren't using a fixed-length or chunked transfer mode.
The loop while(true) in Servlet is infinite even if client browser is closed.
No it isn't.
One way to check, wihin the Servlet, that connection is closed, is using the writer.checkError() method. I tested this fix on Chrome and it works. Your code would be:
boolean error=false;
while (!error) {
//...
writer.write("data: " + /*...*/ "\n");
//writer.flush();
error = writer.checkError(); //internally calls writer.flush()
}
Details:
The PrintWriter's API says:
Methods in this class never throw I/O exceptions, although some of its
constructors may. The client may inquire as to whether any errors have
occurred by invoking checkError().
and the checkError() says:
Flushes the stream if it's not closed and checks its error state

Java RMI server side threading

I'm just getting started with RMI and I'm trying to write a simple program that simulates a train booking system. I have the basics set up - Server, Client, and a Remote object exported. It works fine with one Client connection. However when more than 1 Client connects, the Clients seem to be executing in the same thread. This is the case when I run multiple Clients on the same machine or when I connect a Client from another laptop.
I was under the impression that RMI handled threading on the server side? If not, how do I go about handling multiple Client connections given the code below?
Here are the classes of interest.
Server.....
public class Server {
public Server() {
try {
Booking stub = (Booking) UnicastRemoteObject.exportObject(new BookingProcess(), 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("Booking", stub);
System.err.println("Server Ready");
} catch (RemoteException e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
} catch (AlreadyBoundException e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
}
}
BookingProcess.....(I've left out the private methods that processInput(String input) uses)
public class BookingProcess implements Booking {
private static Journey dublinGalway = new Journey("Dublin to Galway");
private static Journey dublinLimerick = new Journey("Dublin to Limerick");
private static Journey dublinCork = new Journey("Dublin to Cork");
private Journey currentJourney;
private enum State {
INITIAL, JOURNEYS_DISPLAYED, JOURNEY_CHOSEN, ANOTHER_BOOKING_OFFERED, SOLD_OUT;
}
private State currentState = State.INITIAL;
public synchronized String processInput(String input) {
String output = "";
if(currentState == State.INITIAL) {
if(bookedOut()) {
output = "Sorry, there are no seats remaining on any route. Get the bus.";
currentState = State.SOLD_OUT;
}
else {
output = "Please choose a journey to book: " + "1: " + dublinGalway.getDescription() + ", 2: " + dublinLimerick.getDescription() + ", 3: " + dublinCork.getDescription();
currentState = State.JOURNEYS_DISPLAYED;
}
}
else if(currentState == State.JOURNEYS_DISPLAYED) {
output = this.processJourneyChoice(input);
}
else if(currentState == State.JOURNEY_CHOSEN) {
output = "Do you wish to confirm this booking? (y/n)";
if(input.equalsIgnoreCase("y")) {
if(bookingConfirmed()) {
output = "Thank you. Your journey from " + currentJourney.getDescription() + " is confirmed. Hit return to continue.";
//currentState = State.ANOTHER_BOOKING_OFFERED;
}
else {
output = "Sorry, but the last seat on the " + currentJourney.getDescription() + " route has just been booked by another user.";
//currentState = State.ANOTHER_BOOKING_OFFERED;
}
currentState = State.ANOTHER_BOOKING_OFFERED;
}
else if(input.equalsIgnoreCase("n")) {
output = "You have cancelled this booking. Hit return to continue.";
currentState = State.ANOTHER_BOOKING_OFFERED;
}
}
else if(currentState == State.ANOTHER_BOOKING_OFFERED) {
output = "Would you like to make another booking? (y/n)";
if(input.equalsIgnoreCase("y")) {
output = "Hit Return to continue.";
currentState = State.INITIAL;
}
else if(input.equalsIgnoreCase("n")){
output = "Goodbye.";
try {
Thread.currentThread().join(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
currentState = State.INITIAL;
}
}
else if(currentState == State.SOLD_OUT) {
output = "Goodbye.";
}
return output;
}
And finally Client......
public class Client {
public static void main(String[] args) {
Client client = new Client();
client.runClient();
}
public void runClient() {
try {
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
Registry registry = LocateRegistry.getRegistry("localhost");
Booking stub = (Booking) registry.lookup("Booking");
String serverResponse = stub.processInput("begin");
System.out.println("Server: " + serverResponse);
while((serverResponse = stub.processInput(consoleInput.readLine())) != null) {
System.out.println(serverResponse);
if(serverResponse.equals("Goodbye.")) {
break;
}
}
} catch (Exception e) {
System.err.println("Client exception " + e.toString());
e.printStackTrace();
}
}
}
As for as RMI server threads, the answer is that it may or may not run in a separate thread. See the documentation here:
http://docs.oracle.com/javase/6/docs/platform/rmi/spec/rmi-arch3.html
3.2 Thread Usage in Remote Method Invocations
A method dispatched by the RMI runtime to a remote object implementation may or may not execute in a separate thread. The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads. Since remote method invocation on the same remote object may execute concurrently, a remote object implementation needs to make sure its implementation is thread-safe.
You can take server side thread dumps and you would see that the RMI TCP Connection threads IDs keep changing, however as #jtahlborn noticed the server side method is synchronized so it would execute serially, not necessarily in a single thread though.
Your server side processInput() method is synchronized, so, yes, the calls will be handled serially. what does that have to do with RMI?
UPDATE:
if you want to have separate currentState and currentJourney values for each client session, then you need to use the RMI remote session pattern, see this answer for details.

login in flex and java using multithreading

I have problem with my login application in java and flex. we use fingerprint login. the system waits for 60 seconds for any fingerprint input from the user. After that it automatically goes out of the page. The user also has text password option on that page. When user clicks on that option, control goes to some other page. But the problem is whenver user click on text password option, he is redirected but the thread of 60 seconds keep running. Can any one help me how to stop that thread. Here is my code. I am using blocking queue concept to get out of the input screen by inputting some dummy value of one bit.
private void interruptCaptureProcess() {
System.out.println("Interrupting Capture Process.");
ExactScheduledRunnable fingerScanInterruptThread = new ExactScheduledRunnable()
{
public void run()
{
try
{
if (capture != null)
{
DPFPSampleFactoryImpl test = new DPFPSampleFactoryImpl();
samples.put(test.createSample(new byte[1]));
capture.stopCapture();
}
}
catch (Exception e)
{
LOGGER.error("interruptCaptureProcess", e);
e.printStackTrace();
}
}
};
timeOutScheduler.schedule(fingerScanInterruptThread, getTimeOutValue(), TimeUnit.SECONDS);
}
/**
* Scans and Verifies the user finger print by matching it with the previous registered template for the user.
*
* #param userVO is the user value object which has to be verified.
* #return the acknowledgment string according to result for operation performed.
* #throws UserServiceException when there is an error in case of getting user record.
*/
public String verifyUserFingerPrint(Long userId) throws LoginServiceException {
System.out.println("Performing fingerprint verification...\n");
interruptCaptureProcess();
UserVO userVO = null;
try {
userVO = new UserService().findUserById(userId, true);
if (userVO != null) {
stopCaptureProcess();
DPFPSample sample = getSample(selectReader(), "Scan your finger\n");
timeOutScheduler.shutdownNow();
if (sample.serialize().length == 1) {
System.out.println("Coming in code");
return null;
} else if (sample.serialize().length == 2) {
System.out.println("Capturing Process has been Timed-Out");
return TIMEOUT;
}
if (sample == null)
throw new UserServiceException("Error in scanning finger");
DPFPFeatureExtraction featureExtractor = DPFPGlobal.getFeatureExtractionFactory()
.createFeatureExtraction();
DPFPFeatureSet featureSet = featureExtractor.createFeatureSet(sample,
DPFPDataPurpose.DATA_PURPOSE_VERIFICATION);
DPFPVerification matcher = DPFPGlobal.getVerificationFactory().createVerification();
matcher.setFARRequested(DPFPVerification.MEDIUM_SECURITY_FAR);
byte[] tempByte = userVO.getFingerPrint();
DPFPTemplateFactory facotory = new DPFPTemplateFactoryImpl();
for (DPFPFingerIndex finger : DPFPFingerIndex.values()) {
DPFPTemplate template = facotory.createTemplate(tempByte);
if (template != null) {
DPFPVerificationResult result = matcher.verify(featureSet, template);
// Fix of enh#1029
Map<ScriptRxConfigType, Map<ScriptRxConfigName, String>> scriptRxConfigMap = ScriptRxConfigMapSingleton
.getInstance().getScriptRxConfigMap();
Map<ScriptRxConfigName, String> fingerPrintPropertiesMap = scriptRxConfigMap
.get(ScriptRxConfigType.FINGERPRINT);
String fingerPrintDemoMode = fingerPrintPropertiesMap.get(ScriptRxConfigName.DEMOMODE);
if (fingerPrintDemoMode != null && fingerPrintDemoMode.equalsIgnoreCase("DemoEnabled")) {
return "LOGS_MSG_101";
}
// End of fix of enh#1029
if (result.isVerified()) {
System.out.println("Matching finger: %s, FAR achieved: %g.\n" + fingerName(finger)
+ (double) result.getFalseAcceptRate() / DPFPVerification.PROBABILITY_ONE);
return "LOGS_MSG_101";
}
}
}
}
} catch (IndexOutOfBoundsException iob) {
LOGGER.error("verifyUserFingerPrint", iob);
throw new LoginServiceException("LOGS_ERR_101", iob);
} catch (Exception exp) {
LOGGER.error("verifyUserFingerPrint", exp);
System.out.println("Failed to perform verification.");
throw new LoginServiceException("LOGS_ERR_105", exp);
} catch (Throwable th) {
LOGGER.error("verifyUserFingerPrint", th);
throw new LoginServiceException("LOGS_ERR_106", th.getMessage(), th);
}
System.out.println("No matching fingers found for \"%s\".\n" + userVO.getFirstName().toUpperCase());
throw new LoginServiceException("LOGS_ERR_107", null);
}
/* finger scanning process
*/
private void stopCaptureProcess() {
ExactScheduledRunnable fingerScanInterruptThread = new ExactScheduledRunnable() {
public void run() {
try {
DPFPSampleFactoryImpl test = new DPFPSampleFactoryImpl();
samples.put(test.createSample(new byte[2]));
capture.stopCapture();
} catch (Throwable ex) {
ex.printStackTrace();
}
}
};
timeOutScheduler.schedule(fingerScanInterruptThread, getTimeOutValue(), TimeUnit.SECONDS);
}
/**
* API will get the value for the finger scanner time out configuration(Default will be 60 seconds)
*/
private long getTimeOutValue() {
long waitTime = 60;
String configValue = ScriptRxSingleton.getInstance().getConfigurationValue(ConfigType.Security,
ConfigName.FingerprintTimeout);
try {
waitTime = Long.valueOf(configValue);
} catch (NumberFormatException e) {
LOGGER.debug("Configuration value is not a number for FingerTimeOut", e);
}
return waitTime;
}
Stopping blocking tasks in Java is a complicated topic, and requires cooperation between the blocking code and the code that wants to unblock it. The most common way in Java is to interrupt the thread that is blocking, which works if the code that is blocking and the code around it understands interruption. If that's not the case you're out of luck. Here's an answer that explains one way to interrupt a thread that is blocking in an Executor: https://stackoverflow.com/a/9281038/1109

Categories

Resources