Greetings,
I have a servlet which pulls an "action" parameter from a querystring. Based on this string I perform the required action.
What is the best way to check the value of the "action" parameter. Currently my code is a long if, else if, else if, else if...when I'd rather have some kind of mapping from string to method where I didn't have so many branch conditions.
Regards,
Ken
Populate a Map<String, Action> where String represents the condition for which you would like to grab the action and Action is the interface which you've definied for your actions.
E.g.
Action action = actions.get(request.getMethod() + request.getPathInfo());
if (action != null) {
action.execute(request, response);
}
You can find a detailed example in this answer.
One possible way is to keep them in a file (XML file or Properties file).
Load them into the memory. It can be stored in some Map.
Based the key, the operation(value) can be decided.
Maybe using a helper class with an enum type might help:
public class ActionHelper {
public enum ServletAction {
ActionEdit,
ActionOpen,
ActionDelete,
ActionUndefined
}
public static ServletAction getAction(String action)
{
action = action != null ? action : "";
if (action.equalsIgnoreCase("edit"))
return ServletAction.ActionEdit;
else if (action.equalsIgnoreCase("open"))
return ServletAction.ActionOpen;
else if (action.equalsIgnoreCase("delete"))
return ServletAction.ActionDelete;
return ServletAction.ActionUndefined;
}
}
Then, your servlet will have something short and simple like:
ServletAction sa = ActionHelper.getAction(request.getParameter("action"));
switch (sa) {
case ServletAction.ActionEdit:
//
break;
// ... more cases
}
Related
I need specific data for a report, then I gettin all information from a parent object
Object1
It has many attributes, object attributes
Object11, Object12, Object13, attr1, attr2...
The attributes has many attributes too
Object111, Object131, Object132,..
by now I got 5 level data attributes.
When I send information to my report it says, Error: cause:null
object1.getIdObject11().getIdObject111().getDescription;
It trows error because Object111 is null
I tried using
object1.getIdObject11().getIdObject111().getDescription==null?'':object1.getIdObject11().getIdObject111().getDescription;
but it only verify if description is null, and throws the same error
Then I tried to verify Object
if(object1.getIdObject11().getIdObject111() == null) {
var = object1.getIdObject11().getIdObject111().getDescription;
} else {
var = "";
}
But when Object11 is null, it throws same error.
I don't think its a good way doing this for each attribute (have to get like 30 attributes)
if(object1.getIdObject11()!=null) {
if(object1.getIdObject11().getIdObject111()!=null) {
if(object1.getIdObject11().getIdObject111().getIdObject1111()!=null) {
//...
}
}
}
I want to verify if is there a null object and set '' (blank) if it is, with no such a large code(because the gotten params are set inside a report, mixed with letter).
reportline1 = "Area: "+object1.getIdObject11().getIdObject111().getName;
You code breaks Demeter's law. That's why it's better to refactor the design itself.
As a workaround, you can use Optional
var = Optional.ofNullable(object1)
.map(o -> o.getIdObject11())
.map(o -> o.getIdObject111())
.map(o -> o.getDescription())
.orElse("")
The way I would probably do this to extend the functionality of the code easily in the future might take a bit of writing in the beginning but will be easily usable forever.
I would create a new method in your parent class called hasNull that returns a boolean like so:
public boolean hasNull()
{
boolean hasANull = false;
//Call another hasNull() inside of object11 which in turns calls hasNull() in object111 etc.
//If any of the calls return with a true/null value set hasANull to true
return hasANull;
}
This in turn checks to see if the current objects it contains are null. If one of the class variables is another custom class you created you can then add another hasNull into that one and keep going until you get to the lowest level where you can do a specific operation when the value is null such as set it to "".
After implementing this you will be able to just be able to use it like this any time you need it:
if (!object1.hasNull())
{
//Do whatever you want if there are no null values
}
else
{
//Do whatever you want if there is a null value
}
You can also make this a void method if you only want it to toggle the values on the lowest level, and do not need to do anything in either case.
I prefer the solution that gave dehasi.
But you can also do something like that:
getOrElse(() -> object1.getIdObject11().getIdObject111().getDescription(), "")
Where getOrElse is:
public static <T> T getOrElse(Supplier<T> getter, T elseValue) {
try {
return getter.get();
} catch (Exception e) {
// log or do something with it
}
return elseValue;
}
It may be controversial becaouse you use Exception to do this.
You can use this code to check if your object has a null attribute, the object is myclass;
for (Field f : myclass.getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
if (Objects.isNull(f.get(myclass))) {
isLineContainsNull = true;
}
} catch (Exception e) {
log.error(e.getMessage());
}
}
I am using the wikidata toolkit and I want to get a list of all events.
I wrote a EntityDocumentProcessor, where I want to filter for the events out of my dump. Well I know that the event document has the id Q1190554 and that I have to somehow check if the instance of the current itemDocument is an "instance of" (P31) of an event.
#Override
public void processItemDocument(ItemDocument itemDocument) {
boolean isEvent = false;
for (StatementGroup statementGroup : itemDocument.getStatementGroups()) {
switch (statementGroup.getProperty().getId()) {
case "P31": // P31 is "instance of"
isEvent = containsValue(statementGroup, filterClass);
break;
case "P279": // P279 is "subclass of"
if (!isEvent) {
isEvent = containsValue(statementGroup, filterClass);
}
break;
}
}
}
private boolean containsValue(StatementGroup statementGroup, Value value) {
for (Statement s : statementGroup.getStatements()) {
if (value.equals(s.getValue())) {
return true;
}
}
return false;
}
This approach worked pretty good for getting people. But the problem with events is that events like WW2 (https://www.wikidata.org/wiki/Q362) dont have the event directly mapped. The event is somewhere hidden.
Does anyone knows a way how I can easily check if the current itemDocument is an event?
You should follow the hierarchy of the subclass of of the particular instance of to a split. So starting from Q362 you will eventually reach: https://www.wikidata.org/wiki/Q350604 - armed conflict, the presumption being that WWII is everything until prior to that split, namely:
1) world war: https://www.wikidata.org/wiki/Q103495 and
2) war: https://www.wikidata.org/wiki/Q198, then
3) armed conflict: https://www.wikidata.org/wiki/Q350604 which splits to:
1) conflict: https://www.wikidata.org/wiki/Q180684, which now splits to
2) event: https://www.wikidata.org/wiki/Q1190554
And since you are only interested in events, I will do this recursively until I reach the event class.
I have two questions about Java Convention. I try to make use od Robert C. Martin's "Clean Code".
Following case:
public void startProgressIfAllowed() {
try {
tryStartProgressIfAllowed();
} catch (Exception exception) {
// log error
}
}
private void tryStartProgressIfAllowed() {
if (isStartProgressAllowed()) {
stopProgressOnCurrentlyStartedTask();
startProgressOnThisTask();
}
}
private boolean isStartProgressAllowed() {
// Calls JOptionPane.showConfirmDialog with JOptionPane.YES_NO_OPTION.
// Created dialog contains checkbox indicating that saving currently started task is required.
// returns boolean depending on JOptionPane.YES_NO_OPTION clicked button
}
private void stopProgressOnCurrentlyStartedTask() {
// Saves currently started task depending on checkbox selecion property and stops currently started.
// What is the correct way to get checkbox selecion property?
}
Proposed solution:
public void tryStartProgressIfAllowed() {
if (tryToStopProgressOnStartedTaskIfNecessary()) {
startProgressOnThisTask();
}
}
private boolean tryToStopProgressOnStartedTaskIfNecessary() {
// Calls JOptionPane.showConfirmDialog with JOptionPane.YES_NO_OPTION.
// Created dialog contains checkbox indicating that saving currently started task is required.
// Depending on checkbox selecion property saves task.
// returns boolean depending on JOptionPane.YES_NO_OPTION clicked button
}
But this approach doesn't meet the "Command Query Separation" principle, because tryToStopProgressOnStartedTaskIfNecessary(...) method performs some logic and returns success/failure value.
I think this approach also doesn't meet the "One level of abstraction per function" principle, because I suppose "check" and "save" operations are on different levels of abstraction.
Is the method name correct to avoid disinformation? Maybe better name would be tryToStopProgressAndSaveStartedTaskIfNecessary(...)?
Is there any better solution for above problem?
What about the following:
public void tryStartProgressOnThisTaskIfAllowed() {
tryStopTaskInProgressIfAllowed()
if (!isTaskInProgress()) {
tryStartProgressOnThisTask();
}
}
private void tryStopTaskInProgressIfAllowed() {
if (!isTaskInProgress()) {
return;
}
TaskInProgressResult result = whatToDoWithTaskInProgress();
if (result == Result.KEEP) {
return;
} else if (result == Result.DROP)
tryDropTaskInProgress();
} else if (result == Result.SAVE) {
trySaveTaskInProgress();
}
}
About your points:
You now have two separate methods for C and Q
I think the two things whatToDoWithTaskInProgress and tryDropTaskInProgress are the same level of abstraction. If you'd inline the code of one or the other you were absolutely right of course.
I changed some of the method names according to my taste :) The only thing I still don't like is the part "OnThisTask" because this task is somewhat meaningless. Maybe it's only because the rest of the code is unknown maybe OnNextTask or OnNewTask are better.
The problem we were having is that we were thinking in UI terms YES/NO + checkbox value. But it is much better to think in business terms here. I identified three different outcomes that are of interest: KEEP, SAVE, DROP How the answer is obtained should not matter to the calling method.
This seems something to ask on CodeReview, see the drop down at the top left of the page.
An example of how such stateliness is realized in Java SE: the regex Matcher class.
String s = ...
Pattern pattern = Pattern.compile("...");
Matcher m = pattern.matcher(s);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, ... m.group(1) ...);
}
m.appendTail(sb);
with m.matches() and m.lookingAt as alternative circuits too.
In short state is held in a processing class on the actual data (String here).
I have an application server written in java that must use different machine learning models based on the request context. For example my request context looks like
class RequestContext {
String clientId;
String experimentId;
String sessionId;
...
}
Currently I have a delegation logic:
if(requestContext.experimentId == "experiment1"
&& requestContext.clientId == "client1"
){
// use model #1
} else if(requestContext.experimentId == "experiment2"
&& requestContext.clientId == "client1"){
// use model #2
} ...
I could use guava's predicates to express these rules and upon match, delegate to the appropriate model. As a second step, I would like to move these out of the server code to an external configuration store and have the server periodically read from it. This would enable me to not have to deploy server code each time I change the delegation rule. Moreover, I could write a UI that would let the business users define the conditions and the model to use.
My idea is to first specify a list of conditions that are available (in this case, clientId, experimentId, and sessionId) and allow the user to write a simple java-like script to create the conditions, for example one would write
clientId == "client1" && (sessionId != "session1" || experimentId == "experiment1")
then specify a model to use for when this condition is met. What library/techniques will help me parse a user specified predicate logic into a guava predicate-like object?
final Pattern client_pattern = Pattern.compile("clientId\\s+==\\s+\"(.*?)\"");
Function<String, RequestContext> = new Function<String, RequestContext>() {
public RequestContext apply(String s) {
Matcher client_matcher = client_pattern.matcher(s);
String client_id = client_matcher.find() ? client_matcher.group(1) : null;
// similarly for experiment id and session id
return new RequestContext(client_id, exp_id, session_id);
}
};
That does the parsing. Now that you have the request context, the guava predicates are simple:
Predicate<RequestContext> pred_1 = new Predicate<RequestContext>() {
public boolean apply(RequestContext rc) {
return rc.clientId.equals("client1") && rc.experimentId.equals("experiment1");
}
};
You could also write simpler atomic predicates and then use Predicates#and to combine them.
I was surprised to not get any information on Google about "org.apache.cxf.resource.method". Although, there are a lot of interceptors that use it (in the code that I have been given).
For example this (in a custom FaultOutInterceptor):
private boolean isServiceResponseRequested(Message message) {
Method method = (Method) message.getExchange().getInMessage()
.get("org.apache.cxf.resource.method");
if (method != null) {
Class c = method.getReturnType();
if (c != null) {
if (c.getSimpleName().equals(
ServiceResponse.class.getSimpleName())) {
return true;
}
}
}
return false;
}
AbstractAuthorizingInInterceptor also has a reference to it.
Could any one mind explaining the significance of "org.apache.cxf.resource.method" and how and where to 'set' it?
EDIT :
As a hack to achieve the desired, this is what I've done :
I wrote an inInterceptor for Phase.PRE_STREAM, configured in jaxrs:inInterceptors and in the
handleMessage(Message message)
{
Message inMessage = message.getExchange().getInMessage();
Method appMethod = //Logic to determine the method based on the request Url
inMessage.put("org.apache.cxf.resource.method", appMethod);
}
Although, it gives me the desired results, it is totally a hack and doesn't really look correct. Any comments?
org.apache.cxf.resource.method Java method selected by CXF to handle the incoming request. This is done automatically by CXF in the Pre-Stream phase, typically by examining the annotations present on the classes and method of your jaxrs:serviceBeans, especially the #Path, #[HTTPMethod], #Produces, #Consumes, etc. annotations.
If you need more fine-tuned control over which Method is being selected by CXF, it might be more appropriate to implement a ResourceComparitor, rather than implementing an interceptor to try to parse this data out of the Message.