I tried to find a similar question, but I didn't succeed.
In a bean, I'm looping through a ViewEntryCollection several times, adding or deleting entries. Could someone tell me exactly when these objects should be recycled? I want to be able to reuse the whole collection so I don't want to destroy any objects I might still need.
My code:
public static int FTSearchAll(ViewEntryCollection vec, View vw, String cat, String query) throws NotesException {
...
for (ViewEntry ve = nav.getFirst(); ve != null; ) {
ViewEntry next = nav.getNext(ve);
Document doc = ve.getDocument();
if (doc == null)
continue;
try {
Vector v = session.evaluate(query, doc);
if (v != null && v.size() > 0 && (Double) v.elementAt(0) != 0) {
vec.addEntry(ve, false);
} else {
for (ViewEntry dce = vec.getFirstEntry(); dce != null;) {
ViewEntry dcnext = vec.getNextEntry(dce);
if (dce.getNoteID().equals(ve.getNoteID())) {
vec.deleteEntry(dce);
incinerate(dce);
break;
}
dce = dcnext;
}
}
} catch (NotesException ne) {
} finally {
incinerate(ve, doc);
}
ve= next;
}
As always: thanks!
The rule is quite simple: when a Java object pointing to a Notes C object is about to go onto the garbage heap, .recycle() must have been called.
So you need to do that for all entries inside the loop.
My little rule of thumb: the block (think { ... } ) that created a Notes Java object must call its .recycle() function at the end.
Saves you lot of headaches
I see this, but not completely sure whether I miss something or the code keeps its functionality... :S
for (ViewEntry ve = nav.getFirst(); ve != null; ) {
ViewEntry next = nav.getNext(ve);
Document doc = ve.getDocument();
if (doc == null) {
incinerate(ve); // << new
ve = next; // << new
continue;
}
try {
Vector v = session.evaluate(query, doc);
if (v != null && v.size() > 0 && (Double) v.elementAt(0) != 0) {
vec.addEntry(ve, false);
} else {
for (ViewEntry dce = vec.getFirstEntry(); dce != null;) {
ViewEntry dcnext = vec.getNextEntry(dce);
if (dce.getNoteID().equals(ve.getNoteID())) {
vec.deleteEntry(dce);
incinerate(dce, dcnext); // << new
break;
}
incinerate(dce); // << new
dce = dcnext;
}
}
} catch (NotesException ne) {
} finally {
incinerate(ve, doc);
}
ve = next;
}
Maybe it would be better to check another implementation.
Anyway, I recommend you to use the OpenNTF Domino API and get rid of recycle, and you will get also a proper iteration over entries:
http://www.openntf.org/main.nsf/project.xsp?r=project/OpenNTF%20Domino%20API
Related
I'm currently investing a lot of time in cleaning up my code.
I have a lot of If statements that handles my signup form in frontend.
I have a feeling that after reading the book "Clean code". That this is just ugly, however I didn't seem to find any "amazing/incredible" cleanup format for my code below.
lets say I have 15 more if-statements then this will cause a lot of duplicates, so are there any major improvements possible?
User userByUsername = userRepo.findByUsername(user.getUsername());
User userByEmail = userRepo.findUserByEmail(user.getEmail());
if (userByUsername != null && userByEmail != null) {
throw new AccountException("Email and username already exist");
}
if (userByUsername != null) {
throw new AccountException("Username already exist");
}
if (userByEmail != null) {
throw new AccountException("Email already exist");
}
Another example with another method:
public void addConditions(ReservationDto reservationDto) {
long roomId = roomService.findRoomByRoomName(reservationDto.getRoomName()).getRoomId();
// Check for adding room: Roomcapacity for timeslote reached
// If maxCapacityAfternoon reached, then only add to afternoon possible
int roomCapacity = roomService.findRoomByRoomId(roomId).getCapacity();
boolean maxCapacityMorning = roomCapacity <= getNumberOfReservationsForRoomByDateVoormiddag(roomId, reservationDto.getDate());
boolean maxCapacityAfternoon = roomCapacity <= getNumberOfReservationsForRoomByDateNamiddag(roomId, reservationDto.getDate());
boolean isMorning = reservationDto.isMorning();
boolean isAfternoon = reservationDto.isAfternoon();
capacityConditions(reservationDto, maxCapacityMorning, maxCapacityAfternoon);
// Check: Reservation can only be made when it meets the following conditions
// - Same user
// - is active
// - Morning and date overlap
// - Afternoon and date overlap
Reservation mappedReservation = mapReservationDto(reservationDto);
int amountOfReservationsForDay = reservationRepo.existsReservationForDay(mappedReservation.getUsername(), mappedReservation.getDate());
if (isMorning && isAfternoon) {
if (amountOfReservationsForDay > 0) {
throw new ServiceException(RESERVATION_MSG + FOR_FULL_DAY + reservationDto.getDate());
}
if (reservationRepo.existsReservationForMorning(mappedReservation.getUsername(), mappedReservation.getDate()) > 0
|| reservationRepo.existsReservationForAfterNoon(mappedReservation.getUsername(), mappedReservation.getDate()) > 0
) {
throw new ServiceException(RESERVATION_MSG + "in de voor- of namiddag.");
}
}
if (isMorning && !isAfternoon) {
if (amountOfReservationsForDay > 0) {
throw new ServiceException(RESERVATION_MSG + FOR_FULL_DAY + reservationDto.getDate());
}
if (reservationRepo.existsReservationForMorning(mappedReservation.getUsername(), mappedReservation.getDate()) > 0) {
throw new ServiceException(RESERVATION_MSG + "in de voormiddag.");
}
}
if (!isMorning && isAfternoon) {
if (amountOfReservationsForDay > 0) {
throw new ServiceException(RESERVATION_MSG + FOR_FULL_DAY + reservationDto.getDate());
}
if (reservationRepo.existsReservationForAfterNoon(mappedReservation.getUsername(), mappedReservation.getDate()) > 0) {
throw new ServiceException(RESERVATION_MSG + "in de namiddag");
}
}
if (!isMorning && !isAfternoon) {
throw new ServiceException("Selecteer een tijdstip voor uw reservatie");
}
}
As you can see my project has a lot of conditions when I want to add a reservation. These are only the add conditions and don't take into account the room capacity check. Which is a long list of If's as well
You could create an enum for all the data validation exceptions that can be thrown
public enum DataValidationError {
USERNAME_EXISTS,
EMAIL_EXISTS,
...
}
public static class AccountException extends Exception {
private final List<DataValidationError> errors;
public AccountException(List<DataValidationError> errors) {
this.errors = errors;
}
public List<DataValidationError> getErrors() {
return errors;
}
}
Usage:
List<DataValidationError> errors = new ArrayList<>();
User userByUsername = userRepo.findByUsername(user.getUsername());
User userByEmail = userRepo.findUserByEmail(user.getEmail());
if (userByUsername != null) {
errors.add(DataValidationError.USERNAME_EXISTS);
}
if (userByEmail != null) {
errors.add(DataValidationError.EMAIL_EXISTS);
}
if (!errors.isEmpty()) {
throw new AccountException(errors);
}
This way you could add as many errors in the enum and keep adding them to a list and throw it only once at the end.
I am not sure if any really major improvement can be applied here. But for example since you are throwing the same type of exception you might play around your error message and throw exception only once. Like:
if(userByEmail != null || userByUsername != null){
String message = (userByEmail != null ? "Email" : "Username") + " already exist";
if(userByEmail != null && userByUsername != null){
message = "Email and username already exist";
}
throw new AccountException(message);
}
For make the code more extensible and close I would use a chain of validation for this kind of things. If you know about the SOLID principle, you have a problem of SRP and OCP. By implementing a chain of validation, you would have each node have one purpose and you could easily and more validation in the futur. After you just have to create a chain !
The thing is that validation is ONE thing, so I would too create lost of tiny function with good names, so the reader can "escape early" the reading if needed.
Here is the design patern that could help you: https://refactoring.guru/design-patterns/chain-of-responsibility
I think you repository should thow those exceptions too ! If you can't find a user throw an exception in your repository. You'll have less validation all over you code and it's easyer to read.
I'm a Kotlin developer but I'm working on a java project, but when converting the classes through the sdk, this error appears.
How to solve?
fun deviceIsConnected(): Boolean {
var connected = false
val myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
if (myBluetoothAdapter != null && myBluetoothAdapter.isEnabled) {
if (configsAndModels!!.strMACPROBE != null && configsAndModels.strMACPROBE != "") {
val myDevice = myBluetoothAdapter.getRemoteDevice(
configsAndModels.strMACPROBE
)
try {
val m = myDevice.javaClass.getMethod("isConnected", null as Array<Class<*>>?)) //ERROR ON THIS LINE
connected = m.invoke(myDevice, *null as Array<Any?>?) as Boolean //ERROR ON THIS LINE
} catch (e: Exception) {
throw IllegalStateException(e)
}
}
}
return connected
}
JAVA :
public boolean deviceIsConnected() {
boolean connected = false;
BluetoothAdapter myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (myBluetoothAdapter != null && myBluetoothAdapter.isEnabled()) {
if (configsAndModels.getStrMACPROBE() != null && !configsAndModels.getStrMACPROBE().equals("")) {
BluetoothDevice myDevice = myBluetoothAdapter.getRemoteDevice(configsAndModels.getStrMACPROBE());
try {
Method m = myDevice.getClass().getMethod("isConnected", (Class[]) null);
connected = (boolean) m.invoke(myDevice, (Object[]) null);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
}
return connected;
}
Your Java code is explicitly passing a null array as the varargs, which is unnecessary. You could simplify your Java code to the following, which implicitly passes an empty array:
Method m = myDevice.getClass().getMethod("isConnected");
connected = (boolean) m.invoke(myDevice);
Likewise, in Kotlin, you can omit the varargs if you're passing zero values:
val m = myDevice.javaClass.getMethod("isConnected")
connected = m.invoke(myDevice) as Boolean
Java allows the null array for backward compatibility (to versions that used arrays instead of varargs) and because it doesn't have null safety. Since Kotlin doesn't need the backward compatibility, it doesn't need to support null arrays.
I am trying to replace a string pattern for another one with hyperlink, but I am getting java.util.ConcurrentModificationException. The lines of code which the error is pointing don't make sense, so I wasn't able to find out what happened.
// Replace occurrences in all paragraphs
for (XWPFParagraph p : doc_buffer.getParagraphs()) {
List<XWPFRun> p_runs = p.getRuns();
if (p_runs != null) {
for (XWPFRun r : p_runs) {
String text = r.getText(0);
if ((text != null) && (text.contains(pattern))) {
if (pattern.equals("LINK_TO_DOCS")) {
//TODO
String h_url = "http://example.com/linktodocs/";
String h_text = replacement;
// Creates the link as an external relationship
XWPFParagraph temp_p = doc_buffer.createParagraph();
String id = temp_p.getDocument().getPackagePart().addExternalRelationship(h_url, XWPFRelation.HYPERLINK.getRelation()).getId();
// Binds the link to the relationship
CTHyperlink link = temp_p.getCTP().addNewHyperlink();
link.setId(id);
// Creates the linked text
CTText linked_text = CTText.Factory.newInstance();
linked_text.setStringValue(h_text);
// Creates a wordprocessing Run wrapper
CTR ctr = CTR.Factory.newInstance();
ctr.setTArray(new CTText[] {linked_text});
link.setRArray(new CTR[] {ctr});
r = new XWPFHyperlinkRun(link, r.getCTR(), r.getParent());
}
else {
text = text.replaceAll(pattern, replacement);
r.setText(text, 0);
}
}
}
}
}
Console error:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
at releasenotes.ReleaseNotesUpdater.replaceAllOccurrences(ReleaseNotesUpdater.java:263)
at releasenotes.ReleaseNotesUpdater.main(ReleaseNotesUpdater.java:85)
Also, besides this error, I also would like some advice about how can I replace a string pattern for another one with hyperlink. I have searched but I am a bit confused about how it works.
Edit.:
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
public Iterator<E> iterator() {
return new Iterator<E>() {
private final Iterator<? extends E> i = c.iterator();
public boolean hasNext() {return i.hasNext();}
public E next() {return i.next();}
public void remove() {
throw new UnsupportedOperationException();
}
#Override
public void forEachRemaining(Consumer<? super E> action) {
// Use backing collection version
i.forEachRemaining(action);
}
};
}
at java.util.ArrayList$Itr.next(ArrayList.java:859)
#SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
I have found the solution so I am sharing if anyone has the same trouble.
To replace a common run with a Hyperlink run, simply do the following:
String h_url = "http://example.com/index.html";
String h_text = replacement;
// Creates the link as an external relationship
String id = r.getDocument().getPackagePart()
.addExternalRelationship(h_url, XWPFRelation.HYPERLINK.getRelation()).getId();
// Binds the link to the relationship
CTHyperlink link = r.getParagraph().getCTP().addNewHyperlink();
link.setId(id);
// Creates the linked text
CTText linked_text = CTText.Factory.newInstance();
linked_text.setStringValue(h_text);
// Creates a XML wordprocessing wrapper for Run
// The magic is here
CTR ctr = r.getCTR();
ctr.setTArray(new CTText[] { linked_text });
// Stylizing
CTRPr rpr_c = ctr.addNewRPr();
CTColor color = CTColor.Factory.newInstance();
color.setVal("0000FF");
rpr_c.setColor(color);
CTRPr rpr_u = ctr.addNewRPr();
rpr_u.addNewU().setVal(STUnderline.SINGLE);
The code above is inside a loop which is iterating over all runs in a paragraph (r is the current run). So you just have to call r.getCTR() to be able to edit the run.
The reason why the exception was happening, was because I was trying to modify the document structure while going through it in this line:
XWPFParagraph temp_p = doc_buffer.createParagraph();
If anyone has questions, feel free to ask in the comments.
I have a java code in which there are multiple return statements in a single method. But for code cleaning purpose, I can have only one return statement per method. What can be done to overcome this.
Here is a method from my code:-
public ActionForward login(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Kill any old sessions
//request.getSession().invalidate();
DynaValidatorForm dynaform = (DynaValidatorForm)form;
// validate the form
ActionErrors errors = form.validate(mapping, request);
if(!errors.isEmpty()) {
this.saveErrors(request, errors);
return mapping.getInputForward();
}
// first check if token is set
if(!isTokenValid(request, true)) {
String errmsg="There was a problem with your login. Please close your browser then reopen it and try again. Make sure to click the Login button only ONCE.";
request.setAttribute("errormessage", errmsg);
saveToken(request);
return mapping.findForward(ConstantLibrary.FWD_CONTINUE);
}
// check the form for input errors
String errmsg = checkInput(form);
if (errmsg != null) {
request.setAttribute("errormessage", errmsg);
saveToken(request);
return mapping.findForward(ConstantLibrary.FWD_CONTINUE);
}
// no input errors detected
String resumekey = null;
// check for valid login
ObjectFactory objFactory = ObjectFactory.getInstance();
DataAccessor dataAccessor = objFactory.getDataAccessor();
request.setCharacterEncoding("UTF-8");
String testcode = dynaform.getString("testcode").trim();
String studentname = dynaform.getString("yourname").trim();
String password = dynaform.getString("password").trim();
// 4/3/07 - passwords going forward are ALL lower case
if (!CaslsUtils.isEmpty(password)) {
password = password.toLowerCase();
}
try{
resumekey = new String(studentname.getBytes("ISO-8859-1"),"UTF-8");
} catch (Exception e) {
log_.error("Error converting item content data to UTF-8 encoding. ",e);
}
String hashWord = CaslsUtils.encryptString(password);
// Make sure this is short enough to fit in the db
if (hashWord.length() > ConstantLibrary.MAX_PASSWORD_LENGTH) {
hashWord = hashWord.substring(0, ConstantLibrary.MAX_PASSWORD_LENGTH);
}
Login login = dataAccessor.getLogin(testcode, hashWord, false);
if (login == null || !login.getUsertype().equals(Login.USERTYPE_SUBJECT)) {
request.setAttribute("errormessage", "Incorrect test code or password.");
saveToken(request);
return mapping.findForward(ConstantLibrary.FWD_CONTINUE);
}
// Check if the login has expired
if (login.getLoginexpires() != null && login.getLoginexpires().before(new Date())) {
request.setAttribute("errormessage", "Your login has expired.");
saveToken(request);
return mapping.findForward(ConstantLibrary.FWD_CONTINUE);
}
// Check if the password has expired
if (login.getPasswordexpires() != null && login.getPasswordexpires().before(new Date())) {
request.setAttribute("errormessage", "Your login password has expired.");
saveToken(request);
return mapping.findForward(ConstantLibrary.FWD_CONTINUE);
}
HttpSession session = request.getSession();
session.setAttribute(ConstantLibrary.SESSION_LOGIN, login);
session.setAttribute(ConstantLibrary.SESSION_STUDENTNAME, studentname);
List<Testtaker> testtakers = null;
try {
//invalidate the old session if the incoming user is already logged in.
synchronized(this){
invalidateExistingSessionOfCurrentUser(request, studentname, testcode);
testtakers = dataAccessor.getTesttakersByResumeKey(studentname, login);// Adding this code to call getTesttakersByResumeKey instead of getTesttakers to improve the performance of the application during student login
}
} catch (Exception e) {
log.error("Exception when calling getTesttakers");
CaslsUtils.outputLoggingData(log_, request);
throw e;
}
session = request.getSession();
if(testtakers!=null)
{
if(testtakers.size() == 0) {
// new student -> start fresh
log_.debug("starting a fresh test");
// if this is a demo test, skip the consent pages and dump them directly to the select test page
if (login.getTestengine().equals(Itemmaster.TESTENGINE_DEMO)) {
return mapping.findForward("continue-panel");
}
}
// send them to fill out the profile
// check for custom profiles
String[] surveynames = new String[4];
List<Logingroup> logingroups = dataAccessor.getLoginGroupsByLogin(login.getLoginid());
for(Logingroup logingroup : logingroups) {
Groupmaster group = logingroup.getGroupmaster();
log_.debug(String.format("group: {groupid: %d, grouptype: %s, groupname: %s}", new Object[] {group.getGroupid(), group.getGrouptype(), group.getName()}));
Set<Groupsurvey> surveys = group.getGroupsurveys();
if(surveys.size() > 0) {
// grab the first (and only) one
Groupsurvey survey = surveys.toArray(new Groupsurvey[0])[0];
if(group.getGrouptype().equalsIgnoreCase(Groupmaster.GROUPTYPE_CLASS)) {
surveynames[0] = survey.getSurveyname();
} else if (group.getGrouptype().equalsIgnoreCase(Groupmaster.GROUPTYPE_SCHOOL)){
surveynames[1] = survey.getSurveyname();
} else if (group.getGrouptype().equalsIgnoreCase(Groupmaster.GROUPTYPE_DISTRICT)){
surveynames[2] = survey.getSurveyname();
} else if (group.getGrouptype().equalsIgnoreCase(Groupmaster.GROUPTYPE_STATE)){
surveynames[3] = survey.getSurveyname();
}
}
}
// match the most grandular survey
for(int i=0; i < surveynames.length; ++i) {
if(surveynames[i] != null) {
saveToken(request);
return mapping.findForward("student-profile-"+surveynames[i]);
}
}
// no custom profile, send them to the default
saveToken(request);
return mapping.findForward("student-profile");
}
// get the set of availible panels
Set<Panel> availiblePanels = dataAccessor.getAvailiblePanels(login, studentname);
if(availiblePanels.size() == 0) {
// no panels availible. send to all done!
log_.debug(String.format("No panels availible for Login:%s with resumekey:%s", login.toString(), studentname));
session.setAttribute("logoutpage", true);
resetToken(request);
return mapping.findForward("continue-alldone");
}
//Eventum #427 - Prevent test takers from retaking a finished test.
TestSubjectResult testSubjecResult=dataAccessor.getTestSubjectResult(login, resumekey);
if(testSubjecResult != null){
if(testSubjecResult.getRdscore() != null && testSubjecResult.getWrscore() != null && testSubjecResult.getLsscore() != null && testSubjecResult.getOlscore() != null){
if(testSubjecResult.getRdscore().getFinishtime() != null && testSubjecResult.getWrscore().getFinishtime() != null && testSubjecResult.getLsscore().getFinishtime() != null && testSubjecResult.getOlscore().getFinishtime() != null){
log_.debug(String.format("Already completed all the Skill Tests.", login.toString(), studentname));
session.setAttribute("logoutpage", true);
resetToken(request);
return mapping.findForward("continue-alldone");
}
}
}
// get a list of resumeable testtakers
List<Testtaker> resumeableTesttakers = new ArrayList<Testtaker>();
for(Testtaker testtaker : testtakers) {
if(testtaker.getPhase().equals(ConstantLibrary.PHASE_GOODBYE)) {
// testtaker is done with test. skip.
continue;
}
if(testtaker.getCurrentpanelid() == null) {
// testtaker is the profile testtaker
continue;
}
resumeableTesttakers.add(testtaker);
}
// sort them from least recent to latest
Collections.sort(resumeableTesttakers, new Comparator<Testtaker>() {
#Override
public int compare(Testtaker o1, Testtaker o2) {
// TODO Auto-generated method stub
//return 0;
return new CompareToBuilder()
.append(o1.getLasttouched(), o2.getLasttouched())
.toComparison();
}
});
if(resumeableTesttakers.size() == 0 && availiblePanels.size() > 0) {
// nobody is resumeable but there are panels left to take
// send them to the panel choice
// TODO: This is probably a misuse of Struts.
log_.info("No resumeable testtakers. Sending to panel select");
saveToken(request);
ActionForward myForward = (new ActionForward("/do/capstartpanel?capStartPanelAction=retest&lasttesttakerid="
+ testtakers.get(0).getTesttakerid(), true));
return myForward;// mapping.findForward(ConstantLibrary.FWD_CONTINUE + "-panel");
} else {
// grab the one most recently created and take their test
log_.info(String.format("Resuming with choice of %d testtakers", resumeableTesttakers.size()));
// we're forwarding to resume at this point, so we should do the some of the initialization
// that would have happened if we were still using getTesttaker() instead of getTesttakers() above.
session.setAttribute(ConstantLibrary.SESSION_LOGIN, login);
session.setAttribute(ConstantLibrary.SESSION_TESTTAKER, resumeableTesttakers.get(resumeableTesttakers.size()-1));
saveToken(request);
return mapping.findForward(ConstantLibrary.FWD_RESUME);
}
}
It's not a worth changing multiple returns to a single return statement per method. Actually, that will unnecessarily increase the burden of storing the result in a local variable and then making the return finally,
ActionForward result = null;
//scenario 1
result = ...
//scenario 2
result = ...
//scenario 3
result = ...
//finally
return result;
Hope this helps, but, it doesn't make much sense to me
As pointed out by others, having a single return statement does not necessarily make your code cleaner. However, in this case splitting up the method in smaller pieces probably makes the code more readable.
For example, this part:
// first check if token is set
if(!isTokenValid(request, true)) {
String errmsg="There was a problem with your login. Please close your browser then reopen it and try again. Make sure to click the Login button only ONCE.";
request.setAttribute("errormessage", errmsg);
saveToken(request);
return mapping.findForward(ConstantLibrary.FWD_CONTINUE);
}
// check the form for input errors
String errmsg = checkInput(form);
if (errmsg != null) {
request.setAttribute("errormessage", errmsg);
saveToken(request);
return mapping.findForward(ConstantLibrary.FWD_CONTINUE);
}
could be replaced by introducing two methods and using those to write:
If(tokenNotSet() || formHasErrors()){
return mapping.findForward(ConstantLibrary.FWD_CONTINUE);
}
By doing this on multiple places the structure of the algorithm becomes more clear, possibly giving you more insight in how this code could be refactored to adhere to your coding guidelines.
I would set a an action forward variable at the start of the method.
ActionForward actionForwardToReturn = null;
Then replace each of these two lines
return mapping.getInputForward();
return mapping.findForward(ConstantLibrary.FWD_CONTINUE);
with these two lines :
actionForwardToReturn = mapping.getInputForward()
actionForwardToReturn = mapping.findForward(ConstantLibrary.FWD_CONTINUE);
finally return the variable.
return actionForwardToReturn;
This shouldn't be too difficult :)
On a side note... (actually the orginal answer to the question) :
Multiple return statements can make it hard to debug code.
I personally would have just one action object that you return at the end of the method. The benefit of this, is that i can put a break point right on the return statement and look at exactly what that object is.
Any logging or other cross cutting concern I would want to add later, would only have to be done at one point. Otherwise I would have to add a log statement to every line where you are returning.
The complexity added to a method in an attempt to remove multiple return statements is many a times not worth it, especially in a method such as yours.There's nothing wrong with using them in this case.
Like user3580294 there's nothing wrong with multiple return statements. However you could combine the last two if statements since they are essentially returning the same thing.
Use #Octopus 's method if you absolutely have to have one return statement
I have a method what return a list, but when i run the code, appears Unreachable statement
this method come from a aidl file and generate a map with the return.
code bellow:
List<String> list = new ArrayList<String>();
Public List<String> setMethod(Map map) {
ContentValues cv = null;
Iterator i = map.keySet().iterator();
Iterator j = map.values().iterator();
if(map.isEmpty() || map == null) {
return null;
} else {
try {
while(i.hasNext()) {
String str = (String) i.next();
Long l = (Long) j.next();
list.add(str);
cv.put(Storage.STR, str);
if(Provider.insert(Storage.Table, cv) < 0) {
return null;
}
}
if(list.isEmpty() || list == null) {
return null;
} else {
return mPathList;
}
} catch (Exception e) {
return null;
}
return list;
}
Anybody can give me a light what i can make for dolve it?
You are returning from try block as well as catch, so the last return statement will never be reached.
Your code has multiple return paths. You are returning from first if statement if your condition is met, in else part you have try block. In try you are returning based on if as well as else, so if no exception occurs you are guaranteed to return from try block, in case of exception you have a catch statement and you are returning from there as well. So there is no possibility that your code will continue further. Hence the last return statement is unreachable.
Just follow through your code. The last return statement will never be run because every other branch before that leads to an other return statement.