I have the following function :
protected final ResponseBuilderImpl RESPONSE_BUILDER_IMPL = new ResponseBuilderImpl(); // This is taken from jersey-core-1.11.jar
protected Response buildAcceptedResponse(Object entity) {
return buildResponse(entity, Response.Status.ACCEPTED);
}
protected Response buildResponse(Object entity, Response.Status status) {
return RESPONSE_BUILDER_IMPL.status(status).entity(entity).build();
}
I've tested several cases and noticed that only String is not working, and can't figure out why.
I'm using postman, sending some GET requests
switch (whatToTest){
case 1: //working
log.info("testing case of Interger!! ");
int x = 11;
return buildAcceptedResponse(x);
case 2: // getting as a response Unexpected 'e'
String t = "testing string";
log.info("testing case of String !!");
return buildAcceptedResponse(t);
case 3: //working
log.info("testing case of Boolean !! ");
boolean y = true;
return buildAcceptedResponse(y);
case 4: //not working
log.info("testing case of Object !! ");
Object yy = "test object";
return buildAcceptedResponse(yy);
case 5: //working
log.info("testing case of Object from type int !! ");
Object yyy = 1565746;
return buildAcceptedResponse(yyy);
case 6: //working
log.info("testing case of class with strings and ints!! ");
TestClass e = new TestClass(4,new Integer(7),"test1", false);
return buildAcceptedResponse(e);
/// Adding - when using this case - it works fine
case 7:
log.info("mapping to object");
ObjectMapper om = new ObjectMapper();
Object res = null;
String te = "test test";
try {
res = om.writeValueAsString(te);
} catch (IOException ex) {
ex.printStackTrace();
}
return buildAcceptedResponse(res);
I thought that I might have a problem with primitive types, but int and boolean are returning as they should. Also, a class containing a String inside - is also good.Can someone advise why only Strings are not working ?
Adding -
My function uses :
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("test/test")
public Response getTest(String someParam);
// Response is sr311-api\0.11\jsr311-api-0.11-sources.jar
Related
I would like to test method which use another one? I tried do it using Mockito like below:
EDIT: Full method
public String createUrlAddress(TypeOfInformation typeOfInformation, String icao) {
switch (typeOfInformation) {
case METAR:
urlAddress = StaticValues.MAIN_URL_ADDRESS_FOR_METAR + icao;
break;
case TAF:
urlAddress = StaticValues.MAIN_URL_ADDRESS_FOR_TAF + icao + StaticValues.TAF_4_HOURS_BEFORE_NOW;
break;
case CITY_PAIR_METAR:
urlAddress = StaticValues.MAIN_URL_ADDRESS_FOR_CITY_PAIRS
+ pc.getDepartureAndArrivalTime().get("departureTime") //get departure time from hashmap
+ StaticValues.END_TIME_STRING
+ pc.getDepartureAndArrivalTime().get("arrivalTime")
+ StaticValues.STATION_STRING
+ pc.getOriginIcao()
+ ","
+ pc.getDestinationIcao()
+ StaticValues.MOST_RECENT_FOR_TYPED_STATIONS;
System.out.println(urlAddress);
break;
case CITY_PAIR_TAFS:
urlAddress = StaticValues.MAIN_URL_ADDRESS_FOR_CITY_PAIRS_TAFS
+ pc.getDepartureAndArrivalTime().get("departureTime")
+ StaticValues.END_TIME_STRING
+ pc.getDepartureAndArrivalTime().get("arrivalTime")
+ StaticValues.STATION_STRING
+ pc.getOriginIcao()
+ ",%20"
+ pc.getDestinationIcao()
+ StaticValues.MOST_RECENT_FOR_TYPED_STATIONS_TAFS;
System.out.println(urlAddress);
break;
default:
System.out.println("Wrong Type of informations");
}
return urlAddress;
}
Tests:
#Test
public void forGivenTypeOfInformationAndIcaoReturnUrl() {
HashMap<String,Long> departureAndArrivalTimeTest = new HashMap<>();
departureAndArrivalTimeTest.put("departureTime", 1499264449L);
departureAndArrivalTimeTest.put("arrivalTime", 1499282449L);
PageControllerForNearestCity pcSpy = Mockito.spy(pc);
Mockito.when(pcSpy.getDepartureAndArrivalTime()).thenReturn(departureAndArrivalTimeTest);
Mockito.when(pcSpy.getOriginIcao()).thenReturn("EPWA");
Mockito.when(pcSpy.getDestinationIcao()).thenReturn("EDDF");
assertThat(StaticValuesForTest.URL_ADDRESS_FOR_CITY_PAIR_METAR).isEqualTo(xmlParser.createUrlAddress(TypeOfInformation.CITY_PAIR_METAR, "EPGD")); }
How can I use my mocks in that case? Is it good approach or I have to do it in other way? I would like to add that I won't add these variables as arguments for this method.
PS I thought that the method has only one resposibility, just create a string, am I wrong? Should it be divided into another one like a "Service"?
Thank you for support
Your test enters too much in implementation details.
You mock the own processings/logic of your method. So it makes the test brittle and we can wonder what you assert really.
Besides, the test is complicated to read and to maintain.
At last, the processing associated to each case matters. It is the main logic of your method :
case CITY_PAIR_METAR:
urlAddress = StaticValues.MAIN_URL_ADDRESS_FOR_CITY_PAIRS
+ pc.getDepartureAndArrivalTime().get("departureTime") //get departure time from hashmap
+ StaticValues.END_TIME_STRING
+ pc.getDepartureAndArrivalTime().get("arrivalTime") //get arrival time from hashmap
+ StaticValues.STATION_STRING
+ pc.getOriginIcao()
+ ","
+ pc.getDestinationIcao()
+ StaticValues.MOST_RECENT_FOR_TYPED_STATIONS;
System.out.println(urlAddress);
It should be tested without mocking as you actually doing.
To do it, you should separate responsabilities by introducing a new class.
The actual class should only have a controller/dispatcher role and the new class should perform the logic with a public method by case.
In this way, you class under test could have a dependency on this class and you could mock them in a straight way.
Your actual method could finally look like :
private AddressService addressService;
public String createUrlAddress(TypeOfInformation typeOfInformation, String icao) {
switch (typeOfInformation) {
(...)
case CITY_PAIR_METAR:
urlAddress = addressService.createUrl();
break;
(...)
default:
System.out.println("Wrong Type of informations");
}
return urlAddress;
}
#rafaelim After your response I updated my test class and injected mock to the class like below:
#Before
public void setUp() throws Exception {
departureAndArrivalTimeTest = new HashMap<>();
xmlParser = new XmlParser();
pc = new PageControllerForNearestCity();
departureAndArrivalTimeTest.put("departureTime", 1499264449L); //second arg dep time in sec
departureAndArrivalTimeTest.put("arrivalTime", 1499282449L); //second arg arr time in sec
}
#Test
public void forGivenTypeOfInformationAndIcaoReturnUrl() {
PageControllerForNearestCity pcSpy = Mockito.spy(pc);
xmlParser.setPc(pcSpy);
Mockito.when(pcSpy.getDepartureAndArrivalTime()).thenReturn(departureAndArrivalTimeTest);
Mockito.when(pcSpy.getOriginIcao()).thenReturn("EPWA");
Mockito.when(pcSpy.getDestinationIcao()).thenReturn("EDDF");
assertThat(StaticValuesForTest.URL_ADDRESS_FOR_METAR).isEqualTo(xmlParser.createUrlAddress(TypeOfInformation.METAR, "EPGD"));
assertThat(StaticValuesForTest.URL_ADDRESS_FOR_TAF).isEqualTo(xmlParser.createUrlAddress(TypeOfInformation.TAF, "EPGD"));
assertThat(StaticValuesForTest.URL_ADDRESS_FOR_CITY_PAIR_METAR).isEqualTo(xmlParser.createUrlAddress(TypeOfInformation.CITY_PAIR_METAR, "EPGD"));
assertThat(StaticValuesForTest.URL_ADDRESS_FOR_CITY_PAIR_TAF).isEqualTo(xmlParser.createUrlAddress(TypeOfInformation.CITY_PAIR_TAFS, "EPGD"));
}
Test passed, but its a little bit unreadable, I have to work with "clean code" I think.
EDIT:
#davidxxx please look at this:
public class UrlAddressService {
PageControllerForNearestCity pc = new PageControllerForNearestCity();
public String createUrlForMetar() {
String urlAddressForMetars = new StringBuilder()
.append(StaticValues.MAIN_URL_ADDRESS_FOR_CITY_PAIRS)
.append(pc.getDepartureAndArrivalTime().get("departureTime"))
.append(StaticValues.END_TIME_STRING)
.append(pc.getDepartureAndArrivalTime().get("arrivalTime"))
.append(StaticValues.STATION_STRING)
.append(pc.getOriginIcao())
.append(",")
.append(pc.getDestinationIcao())
.append(StaticValues.MOST_RECENT_FOR_TYPED_STATIONS_METARS)
.toString();
return urlAddressForMetars;
}
public String createUrlForTaf() {
String urlAddressForTafs = new StringBuilder()
.append(StaticValues.MAIN_URL_ADDRESS_FOR_CITY_PAIRS_TAFS)
.append(pc.getDepartureAndArrivalTime().get("departureTime"))
.append(StaticValues.END_TIME_STRING)
.append(pc.getDepartureAndArrivalTime().get("arrivalTime"))
.append(StaticValues.STATION_STRING)
.append(pc.getOriginIcao())
.append(",%20")
.append(pc.getDestinationIcao())
.append(StaticValues.MOST_RECENT_FOR_TYPED_STATIONS_TAFS)
.toString();
return urlAddressForTafs;
}
}
And createUrlAddress method:
public String createUrlAddress(TypeOfInformation typeOfInformation, String icao) {
switch (typeOfInformation) {
case METAR:
urlAddress = StaticValues.MAIN_URL_ADDRESS_FOR_METAR + icao;
break;
case TAF:
urlAddress = StaticValues.MAIN_URL_ADDRESS_FOR_TAF + icao + StaticValues.TAF_4_HOURS_BEFORE_NOW;
break;
case CITY_PAIR_METAR:
urlAddress = addressService.createUrlForMetar();
break;
case CITY_PAIR_TAFS:
urlAddress = addressService.createUrlForTaf();
break;
default:
System.out.println("Wrong Type of informations");
}
return urlAddress;
}
Do you think that it is better approach? I cannot reduce code during building a URL String, because there are 3 different parts of code for Tafs and Metars. Could you show me the best way how to test it if my test are bad?
I think you are in the right direction! You are mocking the dependencies of your code and that dependency is exactly the PageControllerForNearestCity!
One observation about the mock, you have to inject it on xmlParser, like this:
#Test
public void forGivenTypeOfInformationAndIcaoReturnUrl() {
// here you created the mock
PageControllerForNearestCity pcSpy = Mockito.spy(pc);
// I'll assume that xmlParser is the subject of your test
// and that you're injecting the mock like code below
xmlParser.setPageController(pcSpy);
// Configure the mock and then you do the assertion
assertThat(...)
}
PS I thought that the method has only one resposibility, just create a
string, am I wrong? Should it be divided into another one like a
"Service"?
Your method is good! It really do one thing and well and that is building an url from TypeOfInformation
My suggestion is that you refactor your code, after you write your test codes and make it pass! You can remove code duplication and make it more readable!
Remeber this:
'Any fool can write code that a computer can understand. Good
programmers write code that humans can understand.'
Martin Fowler
Good coding!
Edit
Some examples of your code with some refactoring
public String createUrlAddress(TypeOfInformation typeOfInformation, String icao) {
String urlAddress;
switch (typeOfInformation) {
case METAR:
urlAddress = StaticValues.MAIN_URL_ADDRESS_FOR_METAR + icao;
break;
case TAF:
urlAddress = StaticValues.MAIN_URL_ADDRESS_FOR_TAF + icao + StaticValues.TAF_4_HOURS_BEFORE_NOW;
break;
case CITY_PAIR_METAR:
// We delegate the build logic to pc because
// all the information needed to build the url
// is in the PageControllerForNearestCity class
urlAddress = pc.urlAddressForCityPairMetar();
break;
case CITY_PAIR_TAFS:
// Same
urlAddress = pc.urlAddressForCityPairTafs();
break;
default:
System.out.println("Wrong Type of informations");
}
return urlAddress;
}
class PageControllerForNearestCity {
public String urlAddressForCityPairMetar() {
return urlBasedOn(StaticValues.MAIN_URL_ADDRESS_FOR_CITY_PAIRSS, ",", StaticValues.MOST_RECENT_FOR_TYPED_STATIONS);
}
public String urlAddressForCityPairTafs() {
return urlBasedOn(StaticValues.MAIN_URL_ADDRESS_FOR_CITY_PAIRS_TAFS, ",%20", StaticValues.MOST_RECENT_FOR_TYPED_STATIONS_TAFS);
}
// This method removes the duplication that I mentioned before
private String urlBasedOn(String mainUrl, String separator, String endString) {
return mainUrl
+ this.getDepartureAndArrivalTime().get("departureTime")
+ StaticValues.END_TIME_STRING
+ this.getDepartureAndArrivalTime().get("arrivalTime")
+ StaticValues.STATION_STRING
+ this.getOriginIcao()
+ separator
+ this.getDestinationIcao()
+ endString;
}
}
Note that after this refactoring, your forGivenTypeOfInformationAndIcaoReturnUrl test method will become much simpler. But you will have to create test for urlAddressForCityPairMetar() and urlAddressForCityPairTafs().
I still new to Junit test. I have a switch-case as code below.
public void manageTrans(ISOMsgZxc isoMsgZxc) {
AbcEntry abcEntry = new AbcEntry();
abcEntry.setEntryMid(isoMsgZxc.getMid());
String mti = isoMsgZxc.getMti() + "." + isoMsgZxc.getProcessingCode().substring(0, 2);
String transType = "";
BigDecimal amt = new BigDecimal("00.000");
switch (mti) {
case "1234.14":
case "0212.02":
transType = "S";
amt = new BigDecimal(isoMsgZxc.getTransactionAmount()).negate();
break;
case "0400.20":
case "0200.22":
transType = "R";
amt = new BigDecimal(isoMsgZxc.getTransactionAmount());
break;
}
abcEntry.setEntryType(transType);
abcEntryRepository.saveAndFlush(abcEntry);
}
Here how I testing it by using #Test
#Test
public void manageTrans() throws Exception {
AbcEntry abcEntry = mock(abcEntry.class);
PowerMockito.whenNew(AbcEntry.class).withNoArguments()
.thenReturn(abcEntry);
ISOMsgZxc isoMsgZxc = new ISOMsgZxc();
isoMsgZxc.setMti("0100");
isoMsgZxc.setMid("0100");
isoMsgZxc.setProcessingCode("000012");
isoMsgZxc.setTransactionAmount("00.000");
txnService.manageTrans(isoMsgZxc);
verify(abcEntry).setEntryMid(isoMsgZxc.getMid());
String asd = "0400.20";
if(asd.equals("0400.20") || (mti.equals("0200.02")))
{
verify(abcEntry).setEntryType("R");
}
verify(abcEntryRepositoryMock).saveAndFlush(abcEntry);
}
So far the testing show pass. But are there any others method to test the switch-case ? What is the best way to test the switch case so all the possible value can be tested? Any help would be greatly appreciated.
Thanks in advance !
It seems like you're trying to test manageTrans, but in a strange fashion due to the structure of your code (mixing business and persistence logic).
You could have a generateEntry(ISOMsgZxc) which creates and returns the AbcEntry:
public AbcEntry generateEntry(ISOMsgZxc isoMsgZxc) {
AbcEntry abcEntry = new AbcEntry();
abcEntry.setEntryMid(isoMsgZxc.getMid());
String mti = isoMsgZxc.getMti() + "." + isoMsgZxc.getProcessingCode().substring(0, 2);
String transType = "";
BigDecimal amt = new BigDecimal("00.000");
switch (mti) {
case "1234.14":
case "0212.02":
transType = "S";
amt = new BigDecimal(isoMsgZxc.getTransactionAmount()).negate();
break;
case "0400.20":
case "0200.22":
transType = "R";
amt = new BigDecimal(isoMsgZxc.getTransactionAmount());
break;
}
abcEntry.setEntryType(transType);
return abcEntry;
}
This will allow you to test generateEntry to verify the entry after:
#Test
public void generateEntry() {
ISOMsgZxc isoMsgZxc = new ISOMsgZxc();
isoMsgZxc.setMti("0100");
isoMsgZxc.setMid("0100");
isoMsgZxc.setProcessingCode("000012");
isoMsgZxc.setTransactionAmount("00.000");
AbcEntry entry = txnService.generateEntry(isoMsgZxc);
//verfiy
verify(abcEntry).setEntryMid(isoMsgZxc.getMid());
Map<String, String> expectedValues = new HashMap<>();
expectedValues.put("0400.20", "R");
expectedValues.put("0200.02", "R");
//...
expectedValues.forEach((input, output) -> verify(input).setEntryType(output));
}
In your production code, simply call:
entryRepo.saveAndFlush(generateEntry())
Easier to maintain (room for validation), easier to test (concerns are separated).
Assuming you want to test the persistence part, you should create another test.
manageTrans would look like this:
public void manageTrans(ISOMsgZxc isoMsgZxc) {
AbcEntry entry = generateEntry();
entryRepo.saveAndFlush(entry);
}
And your test would simply check if the entry exists in the repo after calling manageTrans. Although chances are, saveAndFlush has already been tested, so the manageTrans really wouldn't need testing, as it's implementation consists of already-tested code, and there is no special integration required.
The test for the third test case could look like this.
#Test
public void manageTrans() throws Exception {
ISOMsgZxc isoMsgZxc = new ISOMsgZxc();
isoMsgZxc.setMti("0200");
isoMsgZxc.setMid("0100");
isoMsgZxc.setProcessingCode("220012");
isoMsgZxc.setTransactionAmount("00.000");
//mti should now be = 0200.00, the third case
txnService.manageTrans(isoMsgZxc);
assertThat(abcEntry.getEntryMid(), equalTo(isoMsgZxc.getMid()));
assertThat(abcEntry.getEntryType(), equalTo("R"));
verify(jcbEntryRepositoryMock).saveAndFlush(jcbEntry);
}
To cover the other test cases:
modify the two lines isoMsgZxc.setMti("0200"); and isoMsgZxc.setProcessingCode("220012"); such that they enter the correct case
you will need 5 tests for full coverage
I am trying the following code:
public class StoredProcedureParam
{
private String m_sType;
private String m_sValue;
private String m_sParamName;
public StoredProcedureParam(String a_sParamName, String a_sType, String a_sValue)
{
m_sType = a_sType;
m_sValue = a_sValue;
m_sParamName = a_sParamName;
}
}
ArrayList<StoredProcedureParam> spmArr = new ArrayList<StoredProcedureParam>();
spmArr.add(new StoredProcedureParam("sBridgePhone", "NString", "value1"));
spmArr.add(new StoredProcedureParam("sCallerPaidTelNumber", "NString", "value2"));
spmArr.add(new StoredProcedureParam("sTollFreeTelNumber", "NString", "default"));
spmArr.add(new StoredProcedureParam("sParticipantAccessCode", "NString", "value3"));
spmArr.add(new StoredProcedureParam("sHostPassword", "NString", "value4"));
spmArr.add(new StoredProcedureParam("tNowUtc", "output", "timestamp"));
spmArr.add(new StoredProcedureParam("nStatusCode", "output", "Int"));
if (!m_jdbcWrapper.callStoredProcedure("{call spAddConference(?,?,?,?,?,?,?)}", spmArr)) {
System.out.println("callAddConferenceSp - Failed to execute");
return "";
}
public boolean callStoredProcedure(String a_sStoredProcedure, ArrayList<StoredProcedureParam> a_ParamList)
{
try
{
connect();
m_cStatement = m_Connection.prepareCall(a_sStoredProcedure,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
registerSpParams(a_ParamList);
m_cStatement.execute();
}
catch (SQLException ex)
{
ex.printStackTrace();
return false;
}
finally
{
try
{
m_cStatement.close();
System.out.println("JDBCWrapper - Statement Closed!");
m_Connection.close();
System.out.println("JDBCWrapper - Connection Closed!");
}
catch (SQLException e)
{
e.printStackTrace();
}
}
return true;
}
private void registerSpParams(ArrayList<StoredProcedureParam> a_ParamList) throws SQLException {
if (a_ParamList.size() > 0)
{
for (int i = 1; i <= a_ParamList.size(); i++)
{
StoredProcedureParam spp = a_ParamList.get(i - 1);
switch (TypesEnum.valueOf(spp.getType()))
{
case Integer:
m_cStatement.setInt(spp.getParamName(), Integer.parseInt(spp.getValue()));
break;
case String:
m_cStatement.setString(spp.getParamName(), spp.getValue());
break;
case NString:
m_cStatement.setNString(spp.getParamName(), spp.getValue());
break;
case Timestamp:
m_cStatement.setTimestamp(spp.getParamName(), Timestamp.valueOf(spp.getValue()));
break;
case output:
switch (TypesEnum.valueOf(spp.getValue()))
{
case Integer:
m_cStatement.registerOutParameter(spp.getParamName(), java.sql.Types.INTEGER);
break;
case Timestamp:
m_cStatement.registerOutParameter(spp.getParamName(), java.sql.Types.TIMESTAMP);
break;
default:
break;
}
break;
case bit:
m_cStatement.setByte(spp.getParamName(), Byte.parseByte(spp.getValue()));
break;
case Bigint:
m_cStatement.setBigDecimal(spp.getParamName(), BigDecimal.valueOf(Long.parseLong(spp.getValue())));
break;
}
}
}
}
For some reason I am getting the exception in subject:
com.microsoft.sqlserver.jdbc.SQLServerException: The index 8 is out of range.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:190)
at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.registerOutParameter(SQLServerCallableStatement.java:75)
at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.registerOutParameter(SQLServerCallableStatement.java:1735)
at com.att.ecm.jdbcwrapper.JDBCWrapper.registerSpParams(JDBCWrapper.java:216)
at com.att.ecm.jdbcwrapper.JDBCWrapper.callStoredProcedure(JDBCWrapper.java:138)
at com.client.main.ConferenceStoredProcedures.callAddConferenceSp(ConferenceStoredProcedures.java:74)
at com.main.Main.startFlow(Main.java:51)
at com.main.Main.executeFlow(Main.java:34)
at com.main.Main.main(Main.java:26)
And cannot understand why? As far as I understand I set 7 question marks and set 7 parameters.
So, why does it throws an exception on the 8th index??
Can you advise please?
Best Regards, Tal
The problem was that the stored procedure has more parameters that 7. It has 9.
As I add the 2 parameters and add 2 question marks to the call string - the excption did not happen.
What do you need is a CallableStatement object on which you can prepareCall.
Creates a CallableStatement object for calling database stored procedures. The CallableStatement object provides methods for setting up its IN and OUT parameters, and methods for executing the call to a stored procedure.
To change the above code you need use index in the set methods
likem_cStatement.setInt(i,...
This happened to me when I mapped a parameter and didn't actually use the parameter in the query. Surprised the parameter wasn't simply ignored.
I want to cycle through an ArrayList<String> named fileContent, using the Iterator interface, and I want it to be analyzed one string at a time which should result in a specific state by the switch statement, depending on what string it is.
Object token is supposed to be read as 'Table'.
void process() {
Iterator fileIterator = fileContent.iterator();
int state = 0;
Object token = null;
switch (state) {
case 0:
token = fileIterator.next();
if (token.equals("Table")) {
System.out.println(token);
state = 1;
} else {
System.err.println("Corrupt file format at state 0: "+ token);
System.exit(0);
}
break;
}
}
This doesn't switch state to 1, instead it prints out:
'Corrupt file format at state 0: Table'
So it seems as it reads the Object token correctly as 'Table' but not for the statement 'if (token.equals("Table"))'.
I have also tried 'if (token == ("Table"))'
Can somebody help me?
Looks like you want to equate Strings, try this
void process() {
Iterator fileIterator = fileContent.iterator();
int state = 0;
String token = ""; // notice this
switch (state) {
case 0:
token = ((String)fileIterator.next()).trim(); // notice this
if (token.equals("Table")) {
System.out.println(token);
state = 1;
} else {
System.err.println("Corrupt file format at state 0: "+ token);
System.exit(0);
}
break;
}
}
What makes you think "it reads the Object token correctly as 'Table'"? When the if() fails, then token must be something unlike Table. My guess is that the output is misleading. Try this instead:
System.err.println("Corrupt file format at state 0: ["+ token + "]");
The square brackets around the token will help you see unexpected whitespace characters.
Also note that token might not be a string but return Table when toString() is called on it (which will happen if you append it to a string).
I have the code which can be done in two ways :
SWITCH WITHOUT BREAK(for common code in case)
ResultCodes resCode = ResultCodes.fromResponseCode(resultCode);
switch (resCode) {
case SUCCESS:
if(userIdentity != null)
Logger.logInfo(MODULE, "User Authenticated Successfully, UseIdentity: " +userIdentity);
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = SUCCESS;
break;
case REDIRECT:
url = resultMap.get(WebinKeyConstants.REDIRECTION_URL.val);
Logger.logInfo(MODULE, "Redirecting to URL : " + url);
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = REDIRECT;
break;
case AUTHENTICATION_FAIL:
case USER_ACCOUNT_BLOCKED:
case USER_ACCOUNT_INACTIVE:
case USER_ACCOUNT_SUSPENDED:
case USER_ACCOUNT_TERMINATED:
case USER_ACCOUNT_BLOCKED_ALERT:
case OTP_SEND_SUCCESS:
case USER_PROFILE_NOT_FOUND:
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = ERROR;
break;
}
In above scenario there is only one break implying that all case will execute the same code.
WITH BREAK FOR EACH CASE(for common code in case)
Above scenario can be achieved in other way too, as shown below
ResultCodes resCode = ResultCodes.fromResponseCode(resultCode);
switch (resCode) {
case SUCCESS:
if(userIdentity != null)
Logger.logInfo(MODULE, "User Authenticated Successfully, UseIdentity: " +userIdentity);
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = SUCCESS;
break;
case REDIRECT:
url = resultMap.get(WebinKeyConstants.REDIRECTION_URL.val);
Logger.logInfo(MODULE, "Redirecting to URL : " + url);
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = REDIRECT;
break;
case AUTHENTICATION_FAIL:
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = ERROR;
break;
case USER_ACCOUNT_BLOCKED:
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = ERROR;
break;
case USER_ACCOUNT_INACTIVE:
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = ERROR;
break;
case USER_ACCOUNT_SUSPENDED:
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = ERROR;
break;
case USER_ACCOUNT_TERMINATED:
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = ERROR;
break;
case USER_ACCOUNT_BLOCKED_ALERT:
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = ERROR;
break;
case OTP_SEND_SUCCESS:
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = ERROR;
break;
case USER_PROFILE_NOT_FOUND:
resultMessage=getText(resCode.responseCode.toString());
RESPONSE = ERROR;
break;
}
Which one is better to use? Is there any performance issue?
First switch block has less code and more readable. In case of performance issue, it is negligible.
This would be much clearer:
ResultCodes resCode = ResultCodes.fromResponseCode(resultCode);
if (resCode.isError()) {
resultMessage = resCode.getResultMessage();
RESPONSE = ERROR;
}
public enum ResultCodes {
OK(false), AUTHENTICATION_FAIL(true);
public final boolean isError;
ResultCodes(boolean error) { isError = error; }
public boolean isError() { return isError; }
public String getResultMessage() { return name(); }
}
If you use the second form, then the next developer to see this code will spend hours looking at the individual lines to see what the differences are. Using the first form clearly states "there is no difference here, between these two cases".
This is a no-brainer. Use the first form.
Case statement uses fall through model it means it will execute every case after getting a true case and execute until it won't get a break statement. So in the first case, Suppose that you have found USER_ACCOUNT_BLOCKED_ALERT case true then it will execute OTP_SEND_SUCCESS and USER_PROFILE_NOT_FOUND case as well.
And in the Second case. if it found USER_ACCOUNT_BLOCKED_ALERT as true then it will execute only USER_ACCOUNT_BLOCKED_ALERT block because at end of the block it will find a break and it will get out of switch statement.
Now i think you will get an idea that what is happening.