Where are the request method constants in the Servlet API? - java

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.

Related

Maintain path constants for RestControllers

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";

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 do I use Enum in a proper way?

I'm very to Java and I use enum for the first time like this:
public class Web {
public String baseUrl;
public static enum Environment {
DEVELOPMENT("http://development") ,
PRODUCTION("http://production"),
SANDBOX("http://sandbox");
public final String baseUrl;
private Environment(String baseUrl)
{
this.baseUrl = baseUrl;
}
}
}
The enum Environment has the three constants DEVELOPMENT, PRODUCTION,SANDBOX. The Web class also has the baseUrl to which the Environment's baseUrl to be set ( not sure this is the good practice to do so ).
For setting up the baseUrl I'm currently doing like this :
new Web().setBaseUrl(Web.Environment.PRODUCTION.baseUrl)
I'm not sure this is the right way to use the enums with the classes. Are there any way to directly set Web baseUrl to enums baseUrl.
Am I missing something here.
Thanks in advance
I think you're on the right track, but you're losing some of the strength of Java's enum by accessing the URL in this manner. Instead, use the type of the enum to help ensure that you pass correct values to your method. That is, pass the enum alone, and let the method extract whatever value from it. For example:
new Web().setEnvironment(Web.Environment.PRODUCTION);
Now you can only pass Environments to your Web class, rather than any ol' string.
[Edit] Then your Web.setEnvironment method looks like this:
public void setEnvironment(Environment environment) {
this.baseUrl = environment.getBaseUrl();
}
This way, I can't come along and call new Web().setEnvironment("marvo") by accident. It enforces a certain level of correctness.
And vishal_aim is right. Even with Enums you should practice data hiding and encapsulation, so make the instance variable private, and provide an accessor like getBaseUrl() to retrieve the value.
Rather than using directly Enum's member baseUrl you should make it private and have a getter method in enum class. other than that I think it's ok to use enum this way
Make the enum a top level class/enum.
Add a getter for the baseUrl field.
I think there is nothing wrong with how you use Enum. However the code looks little clumsy:
new Web().setBaseUrl(Web.Environment.PRODUCTION.baseUrl)
I would take the Enum out of the Web class and omit the redundant 'baseUrl' field in the Web class- you do not need it since you have the value in your Enum. Instead of the baseUrl I would have a urlType member of type Environment. Also would be nice to add accessor method to the baseUrl inside the Environment enum
Along with what Bohemian and vishal_aim said, you might be unnecessarily exposing the baseUrl member (or getBaseUrl() method after you refactor it in). Instead pass the enum to the Web class and have it dig the URL from the enum. That way, if you keep the enum inside the Web class, you can keep the baseUrl private.
public void setEnvironment(Environment env) {
baseUrl = env.getBaseUrl();
....
}

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");

java Properties - to expose or not to expose?

This might be an age old problem and I am sure everyone has their own ways.
Suppose I have some properties defined such as
secret.user.id=user
secret.password=password
website.url=http://stackoverflow.com
Suppose I have 100 different classes and places where I need to use these properties.
Which one is good
(1) I create a Util class that will load all properties and serve them using a key constant
Such as :
Util is a singleton that loads all properties and keeps up on getInstance() call.
Util myUtil = Util.getInstance();
String user = myUtil.getConfigByKey(Constants.SECRET_USER_ID);
String password = myUtil.getConfigByKey(Constants.SECRET_PASSWORD);
..
//getConfigByKey() - inturns invokes properties.get(..)
doSomething(user, password)
So wherever I need these properties, I can do steps above.
(2) I create a meaningful Class to represent these properties; say,
ApplicationConfig and provide getters to get specific properties.
So above code may look like:
ApplicationConfig config = ApplicationConfig.getInstance();
doSomething(config.getSecretUserId(), config.getPassword());
//ApplicationConfig would have instance variables that are initialized during
// getInstance() after loading from properties file.
Note: The properties file as such will have only minor changes in the future.
My personal choice is (2) - let me hear some comments?
Do it the most straightforward way (a class with static values):
package com.domain.packagename
public class Properties {
private static String hostName;
public static getHostName() { return hostName; }
private static int port;
public static int getPort() { return port; }
public static void load() {
//do IO stuff, probably
hostName = ??;
port = ??;
//etc
}
}
I find the first approach to be more verbose than necessary. (Especially if the properties are not expected to change very much.) Also, by using the second approach you can handle casting/type issues when the properties are loaded instead of when they are used.
Your option (2) to keep application specific getters sounds better and clean.
public static final keys from an interface had been a bad design in Java for ages.
I guess my first question is why you want to create an instance of something you're saying is a singleton (you mentioned using code like Util.getInstance()). A singleton only has 1 instance so you shouldn't try to instantiate multiple copies in your code.
If the data is static (like this appears to be) I'd create a singleton and retrieve the values from it.
I don't think there is any significant advantage of one method over the other and I don't think the solution (1) is more secure, just because it provides a property key instead of a java getter for getting passwords.
If I had to chose one though I would take option (2).

Categories