I have a about 20 different services which I have to send requests to which require a slightly different set of headers.
The bad legacy code is something like this,
row = db.query_for_service()
if row.type == 'foo1'
// add common headers to request
// add foo1 specific headers 1
// add foo1 specific header 2
// add foo1 specific header 3
else if row.type == 'foo2'
// add common headers to request
// add foo2 specific header 1
...
...
...
else if row.type == foo20
// add common headers to request
// add foo20 specific header 1
// add foo20 specific header 2
// ...
send_request()
What is the best way to refactor this? I have considered some patterns that may work here (strategy, builder) but I am not too sure.
I am currently learning both Java and Python and I would to get thoughts on how the solutions would differ in the two languages
Personally, what I would do is something along these lines.
#Put this in the initialisation
Map foos<row.type,String> = new Map<row.type, String>()
#Populate the map
map.set('a') = 'headerA specific params x=1'
map.set('b') = 'headerB specific params x=2'
map.set('c') = 'headerC specific params y=3'
map.set ...
Map bars<String,String> = new Map<String,String()
bars.set('fooA') = 'a,b'
bars.set('fooB') = 'a,c'
String commonheader = "HTTP/1.1"
#This would be in a method
row = db.query_for_service()
String output_header += commonheader
for i in bars.get(fooN).split(','):
output_header += foos.get(i)
send_request()
In sort of pseudo java/python. The map would be pre-filled with everything you need, then just pick out what you want and attach.
You should try pattern Command.
The pseudo code something like this:
interface Command(){
void execute();
}
class ConcreteCommandA() implements Command {
#Override
void execute(){
// action 1
}
}
class ConcreteCommandB() implements Command {
#Override
void execute(){
// action 2
}
}
and use this structure in your client:
Map<String, Command> commands = new HashMap<String, Command>;
commands.put("action1", new ConcreteCommandA());
commands.put("action2", new ConcreteCommandB());
runCommand(String str){
Command command = commands.get(str);
command.execute();
}
and so on
Related
Let's say I'm writing a bot for a chat (discord, telegram, whatever). The bot can handle chat commands (e.g. !join tells it to join a voice channel on the server).
So somewhere in my code I'd have to parse the command, and I'll have something like
String userMessage = getTheMessageTextSomehow();
// Do something with the message.
I'd like to have a Command class for every one of my commands, and every command would implement a execute() method.
My question is: what's the best practice to create those command objects?
The easiest way would be to have a large CommandFactory or whatever class somwhere, that would be like
if(message.equals(JOIN_MESSAGE) {
return new JoinCommand();
}
if(message.equals(LEAVE_MESSAGE){
return new LeaveCommand();
}
//etc...
That looks like a bad practice and code smell to me.
Is there a better way to do it?
You might want to rely on a Map of Commands.
I'll make it clear that for this usecase, using the Function or Supplier, or whatever standard functional interface is not idiomatic at all. Avoid it.
We can start by building a Command interface
interface Command {
Result execute();
}
Or if you need to accept an argument
interface Command {
Result execute(final Input input);
}
Which will have the required implementations
class JoinCommand implements Command { ... }
class LeaveCommand implements Command { ... }
class NoopCommand implements Command { ... }
And so on.
You'll now need to store those definitions in a key (the command) - value (the implementation) data structure. A Map is perfect for that.
As your command definition will be a String, then
static final Map<String, Command> COMMANDS = new HashMap<>(8);
static {
COMMANDS.put("join", new JoinCommand());
COMMANDS.put("leave", new LeaveCommand());
// And so on
}
The usage is pretty simple
final String userMessage = getTheMessageTextSomehow();
final String commandStr = extractCommand(userMessage);
final Command command = COMMANDS.getOrDefault(commandStr, NOOP_COMMAND);
command.execute();
Or if you'll have to accept an argument
command.execute(yourInput);
You'll also notice I used NOOP_COMMAND, that's just a no-op implementation for Command to avoid dealing with null. It might be, or it might be not, appropriate.
If you're on Java 9+, the Map could also be created using
Map.of(
"join", new JoinCommand(),
"leave", new LeaveCommand(),
// And so on.
)
Usually, it is implemented via mapping. It would be much clearer and readable to implement this with simple Map.
For example:
Map<String, Command> strategies = new HashMap<String, Command>(){{
put(JOIN_MESSAGE, new JoinCommand());
put(LEAVE_MESSAGE, new LeaveCommand());
}};
And its usage:
Command command = strategies.get(messageType);
Moreover, you can define creation strategies (factories) since Java 8 if you need to construct commands depending on some parameters.
Map<String, Function<String, Command>> strategies = new HashMap<String, Command>(){{
put(JOIN_MESSAGE, param -> new JoinCommand(param)); // or JoinCommand::new
put(LEAVE_MESSAGE, param -> new LeaveCommand(param)); // or LeaveCommand::new
}};
And its usage:
Command command = strategies.get(messageType);
command.process(param);
Hello You try Switch Case statement for it, it's easy to understand and in future if you have any changes then it's easy to update the code.
switch(message)
{
case JOIN_MESSAGE:
return new JoinCommand();
break;
case LEAVE_MESSAGE:
return new LeaveCommand();
break;
}
I need to test the following code using JUnit. It looks complex to me and I am not even sure where to take a start from.
I know what the method is doing but I am unable to write a JUnit test for it. Do we follow a pattern or keep some key points in mind while testing any piece of code.
protected WebResource.Builder applyHeaders(WebResource service, List<? extends BaseClientHeader<?>> headers, List<HttpRequestClientHeader> httpHeaders) {
WebResource.Builder wrb = service.getRequestBuilder();
if( headers != null ) {
for( BaseClientHeader<?> header : headers ) {
wrb = wrb.header( ((IEnum)header.getName()).value(), header.getValue() );
}
}
if( httpHeaders != null ) {
for( HttpRequestClientHeader header : httpHeaders ) {
wrb = wrb.header( header.getName().value(), header.getValue() );
}
}
return wrb;
}
Thanks,
Even when this method looks like it does many different things and interacts lots of other code it should be rather simple to test; that’s because it only operates on objects that you hand in. Let’s see…
#Test
public void requestBuilderIsReturned() {
WebResource webResource = Mockito.mock(WebResource.class);
WebResource.Builder webResourceBuilder = mock(WebResource.Builder.class);
when(webResource.getRequestBuilder()).thenReturn(webResourceBuilder);
WebResource.Builder createdBuilder = objectUnderTest.applyHeaders(webResource, null, null);
assertThat(createdBuilder, is(webResourceBuilder));
}
That was pretty straight-forward. In order to verify correct operation on both kinds of headers you need to get a bit tricky, I suppose:
when(webResourceBuilder.header(anyString(), anyString())).thenReturn(webResourceBuilder);
This will simply make the header() method return the object it’s called upon. After that it should be quite simple to verify that the correct methods were called:
verify(webResourceBuilder).header("header1", "value1");
verify(webResourceBuilder).header("header2", "value2");
Armed with this you should be able to unit test the shit out of this particular method. :)
I am developing a Play 2 (v2.2.3) Java application (with Java 8) whose task is to fetch data from two web services and return a composed result.
From my first WS call I get a JSON array object with let's say job listings. Now for every job in this collection I want to call another WS which gives me something like the stock price of the company offering the job. After all this I expect my action to return this new 'enhanced' JSON array where along with each job listing I also see the stock price.
I started putting something together and I managed to get the list of jobs back but somehow the part where I glue the two call together is not working/being called.
public static Promise<Result> index() {
final Promise<WS.Response> resultPromiseJobs = WS.url("https://jobs.github.com/positions.json?description=java").get();
final Promise<Result> result = resultPromiseJobs.flatMap(response -> {
JsonNode jobListings = response.asJson();
// convert jobListings to a collection
List<Job> jobs = ...
// call map on this collection to fetch stock prices for each element
jobs.stream().map(job -> {
Promise<WS.Response> resultPromiseStock = WS.url("secondURL?someQuery=job").get()); // this also returns a promise
// so let's map it to something
// ??? what to map to and how to convert all this to a 'Result'
resultPromiseStock.map();
...
});
});
return result; // what is the correct object to return here?
}
This is basically the same question but about Scala, I am interested in the Java solution
From our chat I can see that you want to you want to map each WS.Response to a JsonNode, with will leave you with a List<Promise<JsonNode>>. Promise.sequence can be used to convert that List<Promise<JsonNode>> to a Promise<List<JsonNode>>, which you can then map to Promise<Result>.
public static Promise<Result> index() {
final Promise<WS.Response> resultPromiseJobs = WS.url("https://jobs.github.com/positions.json?description=java").get();
final Promise<Result> result = resultPromiseJobs.flatMap(response -> {
JsonNode jobListings = response.asJson();
List<Job> jobs = ...
List<Promise<JsonNode>> jsonResultsPromise = jobs.stream().map(job -> {
Promise<WS.Response> resultPromiseStock = WS.url("secondURL?someQuery=job").get()); // this also returns a promise
// map this to the retrieved JsonNode
resultPromiseStock.map(...);
});
// Convert the list of promises into a promise of lists
Promise<List<JsonNode>> jsonResults = Promise.sequence(jsonResultsPromise);
// Now map to Promise<Result>
jsonResults.map(...);
});
return result;
}
The catch here though is that if one of the Promises fails to complete, the entire list will fail. In many cases you might want this to happen if you need all the results. It's easy enough to discard failed Promises from a list in Scala using this method, but I'm not sure how to do it in Java without fold.
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'm new to developing web services in Java (previously I've done them in PHP and Ruby). I'm writing a resource that is of the following format:
<URL>/myService/<domain>/<app_name>/<system_name>
As you can see, I've got a three-level resource identifier, and I'm trying to figure out the best way to parse it. The application I'm adding this new service to doesn't make use of Jersey or any RESTful frameworks like that. Instead, it's just extending HttpServlet.
Currently they're following an algorithm like this:
Call request.getPathInfo()
Replace the "/" characters in the path info with "." characters
Use String.substring methods to extract individual pieces of information for this resource from the pathInfo string.
This doesn't seem very elegant to me, and I'm looking for a better way. I know that using the javax.ws.rs package makes this very easy (using #Path and #PathParam annotations), but using Jersey is probably not an option.
Using only the base HttpServletRequest object and standard Java libraries, is there a better way to parse this information than the method described above?
How about jersey UriTemplate?
import com.sun.jersey.api.uri.UriTemplate;
...
String path = "/foos/foo/bars/bar";
Map<String, String> map = new HashMap<String, String>();
UriTemplate template = new UriTemplate("/foos/{foo}/bars/{bar}");
if( template.match(path, map) ) {
System.out.println("Matched, " + map);
} else {
System.out.println("Not matched, " + map);
}
I've recently solved this issue in one of my applications. My URLs look like this.
/categories/{category}/subcategories/{subcategory}
My problem was that I wanted to map each url pattern with a Java class, so that I could call upon the correct class to render the data.
My application uses Netty, but the URL resolver doesn't use any third party libraries.
What this allows me to do is to parse the URL that is coming in from the browser, generate a map that has key-value pairs (in this case category, and subcategory), as well as instantiate the correct handler for each unique URL pattern. All in all only about 150 lines of Java code for the parsing, the application setup and the definition of the unique URL patterns.
You can view the code for the resolver in GitHub: https://github.com/joachimhs/Contentice/blob/master/Contentice.api/src/main/java/no/haagensoftware/contentice/util/URLResolver.java
UrlResolver.getValueForUrl will return a URLData with the information that you require about your URL:
https://github.com/joachimhs/Contentice/blob/master/Contentice.api/src/main/java/no/haagensoftware/contentice/data/URLData.java
Once this is setup, I can associate URLs with Netty Handlers:
this.urlResolver.addUrlPattern("/categories", CategoriesHandler.class);
this.urlResolver.addUrlPattern("/categories/{category}", CategoryHandler.class);
this.urlResolver.addUrlPattern("/categories/{category}/subcategories", SubCategoriesHandler.class);
this.urlResolver.addUrlPattern("/categories/{category}/subcategories/{subcategory}", SubCategoryHandler.class);
Inside my Handlers I can simply get the parameter map:
String category = null;
logger.info("parameterMap: " + getParameterMap());
if (getParameterMap() != null) {
category = getParameterMap().get("category");
}
I hope that helps :)
I had the same problem as you and, as I didn't find any suitable library, I decided to write URL-RESTify. You may use it or just take a look to write your own solution, it's a small project.
Jersey's UriTemplate mentioned in other answers is good, but it's a big library and it also includes many other dependency libraries.
Tiny solution with no dependency:
https://github.com/xitrum-framework/jauter
I believe first you need to create a framework for storing the REST method and class+method mappings in a property file or in memory data structue. Then write a top level servlet accepting all of your REST request. Depending on the URL starting from your context, you can try to fetch the mapping from your property file/in memory data structure to find out which class and which of its method need to be called. Then making use of reflection you can call the desired method. Take the method response and marshal it into the desired content-type format and send back to the servlet response output stream.
Implemented it myself (check the main method for example), just in case if you would want a custom implementation:
import lombok.AllArgsConstructor;
import lombok.NonNull;
import java.util.*;
public class Template {
final List<TemplateElement> templateElements = new ArrayList<>();
public static void main(String[] args) {
final Template template = new Template("/hello/{who}");
final Map<String, String> attributes = template.parse("/hello/world").get();
System.out.println(attributes.get("who")); // world
}
public Template(#NonNull final String template) {
validate(template);
final String[] pathElements = template.split("/");
for (final String element : pathElements) {
if (isAttribute(element)) {
final String elementName = element.substring(1, element.length() - 1); // exclude { and }
templateElements.add(new TemplateElement(ElementType.ATTRIBUTE, elementName));
} else {
templateElements.add(new TemplateElement(ElementType.FIXED, element));
}
}
}
public Optional<Map<String, String>> parse(#NonNull final String path) {
validate(path);
final String[] pathElements = path.split("/");
if (pathElements.length != templateElements.size()) return Optional.empty();
final Map<String, String> attributes = new HashMap<>();
// ignore the 0th element, it'll always be empty
for (int i = 1; i < templateElements.size(); i++) {
final String element = pathElements[i];
final TemplateElement templateElement = templateElements.get(i);
switch (templateElement.type) {
case FIXED:
if (!element.equals(templateElement.name)) return Optional.empty();
break;
case ATTRIBUTE:
attributes.put(templateElement.name, element);
break;
}
}
return Optional.of(attributes);
}
private void validate(#NonNull final String path) {
if (!path.startsWith("/"))
throw new RuntimeException("A template must start with /"); // a template must start with /
}
private boolean isAttribute(#NonNull final String str) {
return str.startsWith("{") && str.endsWith("}");
}
#AllArgsConstructor
class TemplateElement {
final ElementType type;
final String name;
}
enum ElementType {
FIXED, ATTRIBUTE
}
}
Please point out mistakes if any. Thanks.