Maintain path constants for RestControllers - java

I'd like to know whats the common style to maintain path constants for Rest Controllers.
For example you have something like that:
#RequestMapping(method = RequestMethod.GET, value = ANY_PATH_VALUE)
I do maintain those constants (in the example ANY_PATH_VALUE) at the moment in a class called PathConstants which looks like this:
public abstract class PathConstants {
public static final String ANY_PATH_VALUE = "/path/{SOME_ID}";
...
}
Is it a common way to keep those values straight at the method of the RestController class or is it like I do currently? Or is there a even more common way how to maintain this kind of stuff?

There are two sides to this,
It actually has close to zero performance problem. This has to something with readability.
The first view is keeping the values as native strings there itself in the controllers. This is more readable in the sense that you can directly check the exact API route when you enter the controller.
The second view is keeping it in some other file with static constants. Keeping all the routes like this actually gives you one common place where you can get to know all the API routes you currently support in your application.
I personally prefer the second i.e. keeping all the paths in a file called APIRoutes and further divided by domains.
public class APIRoutes {
public class SYSTEM {
public static final String HEALTH_CHECK = "api/v1/healthcheck";
public static final String LB_HEALTH_CHECK = "lb/v1/healthcheck";
}
public class API {
public static final String SAVE_X = "api/v1/save";
public static final String GET_X = "api/v1/get";
}
public class CACHE {
public static final String RELOAD_X = "cache/v1/load/x";
public static final String RELOAD_Y = "cache/v1/load/y";
}
}
This way in your controller, you have something like
#RequestMapping(method = RequestMethod.GET, value = APIRoutes.API.SAVE_X)

Using constants seems to be a quite reasonable approach. I would, however, define the constants in a final class with a private constructor throwing an AssertionError to enforce noninstantiability:
public final class PathConstants {
// Suppress default constructor for noninstantiability
private PathConstants() {
throw new AssertionError("No instances for you!");
}
public static final String PATH_TO_FOO = "foo";
public static final String PATH_TO_BAR = "bar";
}
Quoting the Item 4 from Effective Java 3rd edition from Joshua Bloch:
Because the explicit constructor is private, it is inaccessible outside the class. The AssertionError isn’t strictly required, but it provides insurance in case the constructor is accidentally invoked from within the class. It guarantees the class will never be instantiated under any circumstances. This idiom is mildly counterintuitive because the constructor is provided expressly so that it cannot be invoked. It is therefore wise to include a comment, as shown earlier.
As a side effect, this idiom also prevents the class from being subclassed. All constructors must invoke a superclass constructor, explicitly or implicitly, and a subclass would have no accessible superclass constructor to invoke.
You also could use something like #RequestMapping("${foo.bar}"), where foo.bar is a value defined in a property souce (such as an application.properties file or YAML variant).
Quoting the Spring MVC documentation:
URI path patterns can also have embedded ${…​} placeholders that are resolved on startup by using PropertyPlaceHolderConfigurer against local, system, environment, and other property sources. You can use this, for example, to parameterize a base URL based on some external configuration.

I think it is a reasonable way to maintain paths. Just make sure you always build the paths from other constants. For example, if your path has version, you define the version as another variable.
public static final String VERSION_1 = "/v1";
public static final String USERS_V1 = VERSION_1 + "/users";

Related

Java - passing an object as a parameter vs. using it's qualified name

I am writing a Java program where a method in one class needs to access a method of an object that is a member of another class. I can do this in at least two different ways, passing as a parameter, or directly accessing the object using the name of the class it is a member of. I find a lot of questions about pass-by-reference vs. pass-by-value, but I can't find anything that addresses this scenario.
Here is some pseudo-code showing what I mean:
// class of object to pass
class MyPrefs {
public String getPref(int i){
String s = ... //some code to get a String indexed by i
return s;
}
}
// class where object is instantiated
class Main {
protected static MyPrefs prefs = new MyPrefs();
}
Here are the two options I am looking at. In a third class, Toolbar, I can do either of these:
// pass as parameter
class Toolbar{
public void applyPrefs(MyPrefs p){
String s = p.getPref(1);
...
}
//or use qualified name of object
class Toolbar{
public void applyPrefs(){
String s = Main.prefs.getPref(1);
...
}
}
It works either way, what I would like to know is what are the merits or problems associated with each method, and if there is another way of doing this that I hadn't considered.
I hope this question doesn't get closed for being opinion-based because technically it is. So, I am not going to claim my answer is based on some undisputed best-practice, but I do believe it is generally accepted as the correct approach.
In my opinion, it would be either a variant of the first, and/or a combination of the two. For example:
public static String getProp(String prop) {
// use java.util.Properties to retrieve the property.
}
This works well when your application has a single property file. In cases you have multiple property files, you need to override this method and pass the path to the correct file.
public static String getProp(String filename, String prop) {
// use java.util.Properties to retrieve the property.
}
Where filename could be just the file name or the fully qualified name (with the path). I tend to keep all my property files in the same folder, so I "hard-code" the path and use that as the base location for my files, so most of the time when using this approach, I only need the actual file name.
I also have created utility methods to obtain specific properties where the name of the method implies what property I am obtaining. This is useful for people that are not too familiarized with the property keys.
public static String getXYZProp() {
// use java.util.Properties to load the properties.
return prop.getProperty("XYZ");
}
Alternatively, you should take advantage of the genetic method you created to do the same
public static String getXYZProp() {
return getProp("XYZ");
}
Or even something like
public static String getXYZProp() {
return getProp("someProps.properties", "XYZ");
}
It is OK to have multiple method that ultimately do the same thing. Think that some users will call the generic ones because they are more familiarized with the property keys while others will rely on method with names that help them figure out what properties they need to retrieve.

Alternative To Singleton Util Class

So I have a class like so:
public class HBaseUtil {
private final String fileName = "hbase.properties";
private Configuration config;
private HBaseUtil() {
try {
config = new PropertiesConfiguration(fileName);
} catch (ConfigurationException e) {
// some exception handling logging
}
}
// now some getters pulling data out of the config object
public static String getProperty(String fieldKeyName) {...}
public static String getColumnFamily(String fieldName) {...}
// ... some more getters
// NO setters (thus making this a read-only class)
}
Thus, basically I have for myself a Singleton class, that the very first time that it is put to use, sets up a configuration object, and then simply keeps listening for get calls. There are a number of problems with this class:
Unit testing the static methods within class HBaseUtil becomes difficult because of a tight-knit coupling between the Singleton and the configurations file.
What I really want is me being able to supply the filename/filename+path to the class so that it can go in there, read the configuration properties from that file and offer them to incoming read requests. One important note here though: I need this flexibility in specifying the properties file ONLY ONCE per JVM launch. So I certainly don't need to maintain state.
Here is what I was able to come up with:
Instead of a Singleton, I have a normal class with all static methods and no explicit constructor defined.
public class HBaseUtil {
// directly start with getters
public static String getProperty(Configuration config, String fieldKeyName) {...}
public static String getColumnFamily(Configuration config, String fieldKeyName) {...}
// ...and so on
}
And then, instead of using the class in my other code like such:
HBaseUtil.getProperty(String fieldKeyName)
I'd use it like so:
Configuration externalConfig = new PropertiesConfiguration("my-custom-hbase.properties");
HbaseUtil.getProperty(externalConfig, fieldKeyName)
My questions:
Am I even thinking in the right direction? My requirement is to have the flexibility in the class only ONCE per JVM. All that needs to be configurable in my project for this, is the location/contents of the HBase .properties file. I was thinking having a Singleton is overkill for this requirement.
What other better approaches are there for my requirement (stated in above point)?
Thanks!
Note: I've read this StackOverflow discussion, but now it's gotten me even more confused.
You should avoid all static methods and instead design a class which does not mandate its lifecycle: it can be a typical immutable POJO with a public constructor.
Then, when you need it as a singleton, use it as a singleton. For testing, use it in some other way.
Usually, dependency injection is the preferred avenue to solve these problems: instead of hard-coding a pulling mechanism for your configuration object, you have the object delivered to any class which needs it. Then you can decide late what bean you will deliver.
Since you are probably not using Spring (otherwise dependency injection would be your default), consider using Guice, which is a very lightweight and non-intrusive approach to dependency injection.

Using Java Spring injection with `public static final` objects (for Jakarta Unstandard)

Disclaimer: I understand that trying to use Spring to inject static variables is considered bad practice (and I know there are ways around it, e.g. here). So ultimately I plan to redesign, but am curious about possible solutions or workarounds.
I am using Jakarta's Unstandard tag library (particularly useConstants) to easily expose public static final objects to my JSP pages. I want these static objects to initialize themselves from my database, which means I need to inject a JDBC Template or Data Source. So I want something like:
public class MyGroup {
// #Autowire or inject somehow?
private static /*final?*/ NamedParameterJdbcTemplate jdbcTemplate;
public static final MyGroup GROUP_A = new MyGroup("GROUP_A");
public static final MyGroup GROUP_B = new MyGroup("GROUP_B");
public static final MyGroup GROUP_C = new MyGroup("GROUP_C");
// Instance fields
private int id;
private String name;
private String description;
/**
* Construct a group
*/
public MyGroup() {}
/**
* Construct a group using information from the database
* #param key the key to match
*/
public MyGroup(String key) {
// Do DB stuff using injected JDBC template
this.id = id_from_DB;
this.name = name_from_DB;
this.description = desc_from_DB;
}
}
In my JSP, I could simply do ${MyGroup.GROUP_A.id} and anywhere else in the Java code I could just MyGroup.GROUP_B.getName().
So the problem is that these groups must be final for the Jakarta library to pick them up, but I can't static initialize them via Spring. Thoughts?
This isn't a problem with spring so much as with a conflict between what you want and what java allows. You cannot delay the assignment of a static final property. It has to be set when the class is loaded. Therefore, by the time spring could inject, it is too late.
If you don't have to have it be final, you can open up some options.
Another possibility is it might be possible to create an aspect when intercepts the access of the property, and returns the value you want rather than the stored value. You could then inject the desired value into the aspect.
I've never done it before specifically with static properties, but I presume it is possible. It is not possible to use constant fields (static final fields bound to a constant string object or primitive value) as a JoinPoint since java requires those to be inlined, but since you are pointing to a non-String object, I think using an aspect could work.
To make sure spring injects into your aspect, make sure you tell spring about it via via something like this:
<bean id="someId" class="com.yourdomain.YourAspect" factory-method="aspectOf"/>

How to call getClass() from a static method in Java?

I have a class that must have some static methods. Inside these static methods I need to call the method getClass() to make the following call:
public static void startMusic() {
URL songPath = getClass().getClassLoader().getResource("background.midi");
}
However Eclipse tells me:
Cannot make a static reference to the non-static method getClass()
from the type Object
What is the appropriate way to fix this compile time error?
The Answer
Just use TheClassName.class instead of getClass().
Declaring Loggers
Since this gets so much attention for a specific usecase--to provide an easy way to insert log declarations--I thought I'd add my thoughts on that. Log frameworks often expect the log to be constrained to a certain context, say a fully-qualified class name. So they are not copy-pastable without modification. Suggestions for paste-safe log declarations are provided in other answers, but they have downsides such as inflating bytecode or adding runtime introspection. I don't recommend these. Copy-paste is an editor concern, so an editor solution is most appropriate.
In IntelliJ, I recommend adding a Live Template:
Use "log" as the abbreviation
Use private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger($CLASS$.class); as the template text.
Click Edit Variables and add CLASS using the expression className()
Check the boxes to reformat and shorten FQ names.
Change the context to Java: declaration.
Now if you type log<tab> it'll automatically expand to
private static final Logger logger = LoggerFactory.getLogger(ClassName.class);
And automatically reformat and optimize the imports for you.
As for the code example in the question, the standard solution is to reference the class explicitly by its name, and it is even possible to do without getClassLoader() call:
class MyClass {
public static void startMusic() {
URL songPath = MyClass.class.getResource("background.midi");
}
}
This approach still has a back side that it is not very safe against copy/paste errors in case you need to replicate this code to a number of similar classes.
And as for the exact question in the headline, there is a trick posted in the adjacent thread:
Class currentClass = new Object() { }.getClass().getEnclosingClass();
It uses a nested anonymous Object subclass to get hold of the execution context. This trick has a benefit of being copy/paste safe...
Caution when using this in a Base Class that other classes inherit from:
It is also worth noting that if this snippet is shaped as a static method of some base class then currentClass value will always be a reference to that base class rather than to any subclass that may be using that method.
In Java7+ you can do this in static methods/fields:
MethodHandles.lookup().lookupClass()
I wrestled with this myself. A nice trick is to use use the current thread to get a ClassLoader when in a static context. This will work in a Hadoop MapReduce as well. Other methods work when running locally, but return a null InputStream when used in a MapReduce.
public static InputStream getResource(String resource) throws Exception {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream is = cl.getResourceAsStream(resource);
return is;
}
Simply use a class literal, i.e. NameOfClass.class
Try it
Thread.currentThread().getStackTrace()[1].getClassName()
Or
Thread.currentThread().getStackTrace()[2].getClassName()
getClass() method is defined in Object class with the following signature:
public final Class getClass()
Since it is not defined as static, you can not call it within a static code block. See these answers for more information: Q1, Q2, Q3.
If you're in a static context, then you have to use the class literal expression to get the Class, so you basically have to do like:
Foo.class
This type of expression is called Class Literals and they are explained in Java Language Specification Book as follows:
A class literal is an expression consisting of the name of a class, interface, array, or primitive type followed by a `.' and the token class. The type of a class literal is Class. It evaluates to the Class object for the named type (or for void) as defined by the defining class loader of the class of the current instance.
You can also find information about this subject on API documentation for Class.
I had the same problem !
but to solve it just modify your code as following.
public static void startMusic() {
URL songPath = YouClassName.class.getClassLoader().getResource("background.midi");
}
this worked fine with me hope it will also work fine with you.
Suppose there is a Utility class, then sample code would be -
URL url = Utility.class.getClassLoader().getResource("customLocation/".concat("abc.txt"));
CustomLocation - if any folder structure within resources otherwise remove this string literal.
Try something like this. It works for me. Logg (Class name)
String level= "";
Properties prop = new Properties();
InputStream in =
Logg.class.getResourceAsStream("resources\\config");
if (in != null) {
prop.load(in);
} else {
throw new FileNotFoundException("property file '" + in + "' not found in the classpath");
}
level = prop.getProperty("Level");

Where are the request method constants in the Servlet API?

I want to write
if (POST.equals(req.getMethod()))
instead of
if ("POST".equals(req.getMethod()))
but I cannot find the constant definitions in the Servlet API (only looked in HttpServletRequest, where I expected them to be).
Where are they (I am using lots of libraries, so if someone else defines them, that would also work)?
It appears that Java EE 6 added the HTTP method names as constants to the javax.ws.rs.HttpMethod annotation interface. Depending on your setup, they may be available to you.
http://docs.oracle.com/javaee/6/api/javax/ws/rs/HttpMethod.html
As far as I know, there aren't any constants for that particular property. You can check out the full list of constants to see what is available, though.
Of course, you can always define your own constants if it makes your code easier to write.
These constants are defined as private in Servlet,
public abstract class HttpServlet extends GenericServlet
implements java.io.Serializable
{
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
...
It's perfectly fine just using the method name literally.
In Spring (so outside JDK, too) you can use:
org.springframework.web.bind.annotation.RequestMethod
This is a enum which provides all HTTP Methods
So you can use RequestMethod.POST.name()
Outside of the JDK, Apache Axis has a public constant for POST (but not for any of the other methods):
org.apache.axis.transport.http.HTTPConstants.HEADER_POST
If you wonder why there aren't any enums defined for this, that's explained in this question and answer: Why HttpRequest.HttpMethod is string instead of Enum?
Bottom line, the HTTP spec does not restrict the set of methods allowed, so additional methods may be used beyond those which are explicitly mentioned in the spec.

Categories