Is it possible to map Spring components through annotations using enums? - java

I'm working with Spring 4, and I have an enum declared like...
public static enum MY_ENUMS {
A(1, "enum1"),
B(2, "enum2");
private final int key;
private final String name;
MY_ENUMS(int key, String name) {
this.key = key;
this.name = name;
}
public String getName() {
return this.name;
}
public int getIndex() {
return this.key;
}
}
Then, from my component I'm attempting to do something like...
// #Named is the equivalent of #Component for this use case
// Making name public and trying this also does not work:
// #Named(MY_ENUMS.A.name)
#Named(MY_ENUMS.A.getName())
public class ServiceImplA implements IService {
#Override
public Object interfaceMethod() {
// Some code specific to ServiceImplA here....
}
}
This doesn't build and I know WHY this doesn't build. Basically, MY_ENUMS.A.getName() doesn't appear to the compilier as being constant, which would mean it cannot be used here. But the point of enums is that they allow you a method to declare constants in a useful way. So, with that being said, is there a way I can specify my component's name by referring to the value in the enum?
I feel this should be possible given that enums are a special case/implementation of constant values but I can't think of a way to work around Spring (or maybe Java's) expectation that the value of the annotation be a straight up constant.

is there a way I can specify my component's name by referring to the
value in the enum?
No, there is not. If the annotation attribute was expecting an enum, you could just use the enum. But invoking a method does not resolve to a constant expression. You might think that you could make the field public and access it directly
#Named(MY_ENUMS.A.name)
but that won't work either because MY_ENUMS.A.name isn't a constant expression either.
The actual reason theat isn't a constant expression is that an enum constant is basically a variable. There is such a thing as a constant variable, which is a constant expression. For a variable to be a constant variable, it needs to be final and initialized with a constant expression. An enum constant is final but is not initialized with a constant expression. Basically an enum constant is compiled to
public static final YourEnum constant = new YourEnum();
The new YourEnum() expression is not a constant expression. And therefore the constant is not a constant variable and can't be used to resolve a String variable which it may be a constant variable.

Related

Explain of a ENUM definition in JAVA

All:
I am on first day reading team's code(the one wrote this left...):
There is one enum definition confused me so much:
/**
* Enum defines the processing stages and the order
*
*/
public enum ProcessStage {
/*
* Individual stages in the process.
* Order of processing is based on the order of listing.
*/
EXTRACT("Extraction", "EXTRACTED", "EXTRACTION_FAILED"),
ROUTE("Routing", "ROUTED", "ROUTE_FAILED"),
PUBLISH("Publishing", "PUBLISHED", "PUBLISH_FAILED");
private String detailedName;
private String successState;
private String failedState;
private ProcessStage(String detailedName, String successState, String failedState) {
this.detailedName = detailedName;
this.successState = successState;
this.failedState = failedState;
}
public String getSuccessState() {
return successState;
}
public String getFailedState() {
return failedState;
}
/**
* Factory method to provide the ProcessStage from its success or failed state value stored in DB.
* #param state
* #return ProcessStage
*/
public static ProcessStage getProcessStage(String state) {
for(ProcessStage ps: ProcessStage.values()) {
if(ps.getSuccessState().equals(state) || ps.getFailedState().equals(state)) {
return ps;
}
}
return null;
}
public String toString() {
return detailedName;
}
}
I wonder if anyone give me some simple introduction about how to read this(like what kinda syntax it uses)? The most confused part is:
EXTRACT("Extraction", "EXTRACTED", "EXTRACTION_FAILED"),
ROUTE("Routing", "ROUTED", "ROUTE_FAILED"),
PUBLISH("Publishing", "PUBLISHED", "PUBLISH_FAILED");
I do not quite understand what this means and how to use this.
And why there are a lot of methods defined inside it and how to use method with a enum variable?
Thanks
Enum
The enum declaration defines a class (called an enum type). The enum
class body can include methods and other fields. The compiler
automatically adds some special methods when it creates an enum.
enums are special type of class. Instead of creating singleton pattern using regular class or to create constants, like WeekDays, we can use enum in such places. Here
EXTRACT("Extraction", "EXTRACTED", "EXTRACTION_FAILED"),
Here EXTRACT is an enum constant meaning it is an instance of the classProcessStage and also all other enum constants(ROUTE, PUBLISH). All costants of enum are unique objects, meaning they are singleton instance created in the jvm and enum makes sure the instances are unique. You need not to put additional effort to create singleton pattern.
The above code is not only declaration, it is also calling the constructor with three String parameters to create the instance.
private ProcessStage(String detailedName, String successState, String failedState) {
this.detailedName = detailedName;
this.successState = successState;
this.failedState = failedState;
}
why there are a lot of methods defined inside it?
Since it is also a class, it can have methods like any other classes. But the restriction is, it cannot be inherited, because internally enum extens the class Enum<E extends Enum<E>> class.
how to use method with a enum variable?
EXTRACT.getFailedState() //returns "EXTRACTION_FAILED"
Keep in mind, without seeing more of the code, I can't be exactly sure what this particular enum is being used for.
So, Let's say we have a method somewhere, where a process is passed through.
public void doSomething(Process process) {}
Now, let's assume that the purpose of this method is to check the status of the process and then do some logic based upon that result. This would entail doing something like the following
public void doSomething(Process process) {
if(ProcessStage.EXTRACT.equals(process.getStage()) {
//do something here...you will have access to the methods within
//the enum
}
}
Without knowing more, this is all I can give you. I hope this gives you a slightly better understanding of what that enum is doing

Including computed `static final` property in an annotation

This works,
#JsonRootName(Bay.PLURAL_FORM)
public class Bay {
public static final String PLURAL_FORM = "bays";
This does not (shows error in Eclipse: The value for annotation attribute JsonRootName.value must be a constant expression):
#JsonRootName(Bay.PLURAL_FORM)
public class Bay {
public static final String PLURAL_FORM =
English.plural(CaseFormat.UPPER_CAMEL.to(
CaseFormat.LOWER_CAMEL, Bay.class.getSimpleName()));
Is there a way to include a computed static final in an annotation?
No, there isn't. The annotation attribute values must be constant expressions. (Not exactly, the real value accepted depends on the return type of the annotation method. It's all described here.)
What you can do, however, is give it a key (a String value, enum value, or Class object) that can refer to a value retrieved at runtime. That's how you'll get your dynamic value.

Instantiate enum class

Consider I am having the following enum class,
public enum Sample {
READ,
WRITE
}
and in the following class I am trying to test the enum class,
public class SampleTest {
public static void main(String[] args) {
testEnumSample(Sample.READ);
}
public static void testEnumSample(Sample sample) {
System.out.println(sample);
}
}
Here I am specifying Sample.READ then passing it as the parameter to the method testEnumSample.
Instead if we want to instantiate the enum class and pass it as parameter what we need to do?
Here I need to specifying Sample.READ to pass it as parameter. Instead if we want to instantiate the enum class and pass it as parameter what we need to do?
What would "instantiate the enum class" even mean? The point of an enum is that there are a fixed set of values - you can't create more later. If you want to do so, you shouldn't be using an enum.
There are other ways of getting enum values though. For example, you could get the first-declared value:
testEnumSample(Sample.values()[0]);
or perhaps pass in the name and use Sample.valueOf:
testEnumSample("READ");
...
Sample sample = Sample.valueOf(sampleName);
If you explained what you were trying to achieve, it would make it easier to help you.
Internally, enums will be translated to something like this
class Sample extends Enum {
public static final Sample READ = new Sample("READ", 0);
public static final Sample WRITE = new Sample("WRITE", 1);
private Sample(String s, int i)
{
super(s, i);
}
// More methods, e.g. getter
}
They should not and cannot be initialized.
Enums doesn't support public constructors and hence, cannot be instantiated. Enums are for when you have a fixed set of related constants. Exactly one instance will be created for each enum constant.
Check my answer in another post.
There are 2 ways:
Use Enum.valueOf() static function, then cast it into your enum type.
Enum v = Enum.valueOf(TheEnumClass, valueInString);
Use class.getEnumConstants() function to get the list of the enum constants, and loop this list and get.
Plugins[] plugins = Plugins.class.getEnumConstants();
for (Plugins plugin: plugins) {
// use plugin.name() to get name and compare
}
You cannot create a new enum instance. Otherwise it won't be an enum.
You can reference an already existing enum. As in your example
Sample sample = Sample.READ;
The elements within an Enum are objects that are instances of the class.
You no need to create an object of Enum.
Here is a similar issue
Refer this
You cannot instantiate an Enum, thats the whole point of having an Enum.
For example you would use enum when defining properties of some thing which would never change like:
enum TrafficLight {
RED("stop"),
YELLOW("look"),
GREEN("go")
}
private string value;
private TrafficLight(String value) {
this.value = value;
}
public getValue() {
return value;
}
Now if you want to get the value of the enum, you can use valueOf method of enums. The static methods valueOf() and values() are created at compile time and do not appear in source code. They do appear in Javadoc, though;
TrafficLight trafficLight = TrafficLight.valueOf("RED")
String value = trafficLight.getValue();
If you do TrafficLight.valueOf("XYZ"), it will throw an IllegalArgumentException
I'm answering to the first question. You can easily do it like this:
public static void main(String[] args) {
Sample.READ.testEnumSample();
}
public enum Sample {
READ,
WRITE;
public void testEnumSample() {
System.out.println(this);
}
}
Fetch a good book on Java Basics and read it.
Anyways, Enums in java are classes with fixed number of objects and objects are defined by its attributes.
Again, you can read something about it here

The values of an enumerated type are static variables of that type. True?

The values of an enumerated type are static variables of that type.
Far as i know, the variables are referenced, by the refererence variable but there is no new operator to instantiate an enum object. But is it like how you can initialize an array?
Is this true or false?
Yes, the literals of an enum type are public static final variables.
Simplified, it looks like this:
public final enum FooEnum {
A, B
}
public final class BarEnum {
public static final BarEnum A = new BarEnum();
public static final BarEnum B = new BarEnum();
}
In reality, there is a bit more stuff there, such as the list of all enumeration literals, a String identifier (the enum value knows its name), an ordinal number and a private Constructor to prevent instantiation (all omitted for clarity of code since question was only about the static)
Afaik enums are converted to classes and yes the values are static fields in this class: http://theopentutorials.com/tutorials/java/enum/enum-converted-to-class/

creating an enum/final class in java

I'm trying to figure out the best way to create a class whose sole purpose is to be a container for global static variables. Here's some pseudocode for a simple example of what I mean...
public class Symbols {
public static final String ALPHA = "alpha";
public static final String BETA = "beta";
/* ...and so on for a bunch of these */
}
I don't need constructors or methods. I just need to be able to access these "symbols" from everywhere simply by calling: Symbols.ALPHA;
I DO need the actual value of the String, so I can't use an enum type. What would be the best way to accomplish this?
Well, it's not clear what else you need beyond the code you've already given - other than maybe making the class final and giving it a private constructor.
However, in order to avoid accidentally using an inappropriate value, I suspect you would be better off making this an enum, like this:
public enum Symbol {
ALPHA("alpha"),
BETA("beta");
private final String value;
private Symbol(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
That way:
You can't accidentally use Symbol.ALPHA where you're really just expecting a string
You can't accidentally use a string where you're really expecting a symbol
You can still easily get the string value associated with a symbol
You can switch on the different symbol values if you need to
You can do that using an interface. No need to construct, values are public, static and final, and can obviously be strings. Such an interface would look similar to your class:
public interface Symbols {
public static final String ALPHA = "alpha";
public static final String BETA = "beta";
/* and so on */
}
You can access the fields directly from everywhere in your code (given it's public) as Symbols.ALPHA etc.
Or, you can use an enum even though you want strings - ALPHA.toString() will return "ALPHA" (and if you want a slightly different string, you can override toString())
Are these configuration parameters or simply "constants" which don't change no matter what? For the former, I'd rather create a configuration class and instantiate it with different values for each environment. Then simply use dependency injection to inject these configurations in different classes. If your requirement is the latter or you are not using DI (Spring/Guice), static classes/interfaces are good to go.

Categories

Resources