Inject Dependency Value Into Enum [duplicate] - java

This question already has answers here:
Using Spring IoC to set up enum values
(13 answers)
Closed 7 years ago.
I have the following enum:
public class Wrapper(){
public enum MyEnum{
A("a_id", "a_source", "a_target"),
B("b_id", "b_source", "b_target"),
...
Z("z_id", "z_source", "z_target"),
String id;
String source;
String target;
myEnum(String i, String s, String t){
id = i;
source = s;
target = t;
}
}
}
If possible I would like to be able to specify the enum parameters (e.g. "a_id") in application.properties so that I can modify them and inject them in as needed. I was initially thinking of something like:
public class Wrapper(){
#Value("${a.id}")
private String A_ID;
#Value("${a.source}")
private String A_SOURCE;
#Value("${a.target}")
private String A_TARGET;
public enum MyEnum{
A(A_ID, A_SOURCE, A_TARGET),
...
}
}
with application.properties looking like:
a.id=a_id
a.source=a_source
a.target=a_target
The problem is that I cannot call A_ID inside the enum without making it static but if I make it static I cannot perform dependency injection (from my understanding).
What would be the best approach to having those strings externally configurable and injected in ?

Possibly this guy has the answer: https://stackoverflow.com/a/711022/4546150
As dnault said, trying to get configuration values from application.properties wont be possible with Spring - you would need to guarantee that Spring has loaded and parsed the configuration, then try to inject it into a static object.
But, as the SO post I linked mentions - do you need to use Springs configuration loading for this? I believe Resource Bundle was mentioned as an alternative:
public enum MyEnum {
A;
public final String id;
public final String source;
public final String target;
MyEnum() {
this.id = BUNDLE.getString("A.id");
this.source = BUNDLE.getString("A.source");
this.target = BUNDLE.getString("A.target");
}
private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(...);
}

You can't do it. But you can have:
public enum MyEnum {
A, B, C, .... Z;
String idKey() { return name().toLowerCase() + ".id"; }
String sourceKey() { return name().toLowerCase() + ".source"; }
String targetKey() { return name().toLowerCase() + ".target"; }
};
Then you can have property file as you've define and then somewhere in the client code:
MyEnum e = ...
properties.getProperty(e.idKey());

Related

Java nested POJO update based on dot annotation

I have a nested POJO structure defined something like this,
public class Employee {
private String id;
private Personal personal;
private Official official;
}
public class Personal {
private String fName;
private String lName;
private String address;
}
public class Official {
private boolean active;
private Salary salary;
}
public class Salary {
private double hourly;
private double monthly;
private double yearly;
}
I get updates from a service with dot annotaion on what value changed, for ex,
id change --> id=100
address change --> personal.address=123 Main Street
hourly salary change --> official.salary.hourly=100
This POJO structure could be 3-4 level deeps. I need to look for this incoming change value and update the corresponding value in POJO. What's the best way of doing it?
If you would like to create Java objects that allows you to edit fields. You can specify your object fields with the public/default/protected access modifiers. This will enable you to get and set fields such as personal.address or official.salary.hours
This approach is typically frowned upon as the object is no longer encapsulated and any calling methods are welcome to manipulate the object. If these fields are not encapsulated with getters and setters, your object is no longer a POJO.
public provides access from any anywhere.
default provides access from any package
protected provides access from package or subclass.
public class Employee {
public String id;
public Personal personal;
public Official official;
}
public class Personal {
public String fName;
public String lName;
public String address;
}
Here's a quick approach using reflection to set fields dynamically. It surely isn't and can't be clean. If I were you, I would use a scripting engine for that (assuming it's safe to do so).
private static void setValueAt(Object target, String path, String value)
throws Exception {
String[] fields = path.split("\\.");
if (fields.length > 1) {
setValueAt(readField(target, fields[0]),
path.substring(path.indexOf('.') + 1), value);
return;
}
Field f = target.getClass()
.getDeclaredField(path);
f.setAccessible(true);
f.set(target, parse(value, f.getType())); // cast or convert value first
}
//Example code for converting strings to primitives
private static Object parse(String value, Class<?> type) {
if (String.class.equals(type)) {
return value;
} else if (double.class.equals(type) || Double.class.equals(type)) {
return Long.parseLong(value);
} else if (boolean.class.equals(type) || Boolean.class.equals(type)) {
return Boolean.valueOf(value);
}
return value;// ?
}
private static Object readField(Object from, String field) throws Exception {
Field f = from.getClass()
.getDeclaredField(field);
f.setAccessible(true);
return f.get(from);
}
Just be aware that there's a lot to improve in this code (exception handling, null checks, etc.), although it seems to achieve what you're looking for (split your input on = to call setValueAt()):
Employee e = new Employee();
e.setOfficial(new Official());
e.setPersonal(new Personal());
e.getOfficial().setSalary(new Salary());
ObjectMapper mapper = new ObjectMapper();
setValueAt(e, "id", "123");
// {"id":"123","personal":{},"official":{"active":false,"salary":{"hourly":0.0,"monthly":0.0,"yearly":0.0}}}
setValueAt(e, "personal.address", "123 Main Street");
// {"id":"123","personal":{"address":"123 Main Street"},"official":{"active":false,"salary":{"hourly":0.0,"monthly":0.0,"yearly":0.0}}}
setValueAt(e, "official.salary.hourly", "100");
// {"id":"123","personal":{"address":"123 Main Street"},"official":{"active":false,"salary":{"hourly":100.0,"monthly":0.0,"yearly":0.0}}}

Enums in Java VS Enums in C# [duplicate]

This question already has answers here:
C# vs Java Enum (for those new to C#)
(13 answers)
Is it possible to add custom properties to c# enum object?
(2 answers)
Closed 2 years ago.
I have a very basic question. In Java, it is possible to point attributes and variables to Enums, such as:
public enum DayTime{
Morning("Morning"),
Afternoon("Afternoon"),
Night("Night");
private string description;
Daytime(string description){
this.description = description;
}
public string getDescription(){
return description;
}
}
Is it possible to apply the same concept to C#? I am trying to get modular descriptions to products, whereas their name, contents and characteristics would be shown in a string of text, and Enums looked like the best alternative to modify this text according to which characteristic is selected.
C# enums are very basic compared to Java enums. If you want to simulate the same kind of behavior you need to use a class with an inner enum:
using System.Collections.Generic;
public sealed class DayTime
{
public static readonly DayTime Morning = new DayTime("Morning", InnerEnum.Morning);
public static readonly DayTime Afternoon = new DayTime("Afternoon", InnerEnum.Afternoon);
public static readonly DayTime Night = new DayTime("Night", InnerEnum.Night);
private static readonly List<DayTime> valueList = new List<DayTime>();
static DayTime()
{
valueList.Add(Morning);
valueList.Add(Afternoon);
valueList.Add(Night);
}
//the inner enum needs to be public for use in 'switch' blocks:
public enum InnerEnum
{
Morning,
Afternoon,
Night
}
public readonly InnerEnum innerEnumValue;
private readonly string nameValue;
private readonly int ordinalValue;
private static int nextOrdinal = 0;
private string description;
internal DayTime(string name, InnerEnum innerEnum)
{
this.description = name;
nameValue = name;
ordinalValue = nextOrdinal++;
innerEnumValue = innerEnum;
}
public string Description
{
get
{
return description;
}
}
//the following methods reproduce Java built-in enum functionality:
public static DayTime[] values()
{
return valueList.ToArray();
}
public int ordinal()
{
return ordinalValue;
}
public override string ToString()
{
return nameValue;
}
public static DayTime valueOf(string name)
{
foreach (DayTime enumInstance in DayTime.valueList)
{
if (enumInstance.nameValue == name)
{
return enumInstance;
}
}
throw new System.ArgumentException(name);
}
}
Given this complexity, it may be best to rewrite your logic in a way that's more natural for C# without using enums.

How to make the value of a String variable not change after once assigned? [duplicate]

This question already has answers here:
Declare final variable, but set later
(7 answers)
Closed 5 years ago.
How can I make sure that the value of String variable doesnot change after being assigned once? Assignment is not at the time of declaration.
More clarity :-
String x = y; (y is another string)
Even if y changes x should not change. How to make sure this?
What I have tried :-
Created a custom class:-
public class MyDs {
private final String unitName;
public MyDs(String iUnitName){
unitName = iUnitName;
}
public String getUnitName(){
return unitName;
}
}
in the main method :-
String iName = "xyz";
MyDs MyDsObj = new MyDs(iName);
But even after this, the value changes when the variable changes.
How can I solve this issue?
Your class be should be design as mentioned in below code
public class TestingClas {
private String name;
public void setName(String name) {
if (this.name == null && name != null)
this.name = name;
}
public String getName() {
return name;
}
}
Now use below code for testing purpose
TestingClas testingClas = new TestingClas();
testingClas.setName("Abdul Waheed");
testingClas.setName("You cannot change me any more now");
String updatedString = testingClas.getName();
updatedString variable will be having old value
as far as I understand ,you should design your class in a way that your variable should be final . with this approach you set it in constructor and then nothing can make it changes. even the referance it is holding is changed the value remains the same I mean a new object is created in heap and value of your final variable is kept same. below is a kind of design which makes the variable x set once and never be able to changed afterwards. Of course this is in instance scope, for class scope you can make your class singelton etc.
public class Test {
private final String x;
private String y;
public Test(String x){
this.x=x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
public String getX() {
return x;
}
}
Change your MyDs class to a singleton class
Making this a singleton class ensures that the final String unitName is updated only once and then it will cannot be altered again.
public class MyDs {
private final String unitName;
private static MyDs myDs;
public static MyDs getMyDsObject(String iUnitName) {
if (myDs == null) {
myDs = new MyDs(iUnitName);
}
return myDs;
}
private MyDs(String iUnitName) {
unitName = iUnitName;
}
public String getUnitName() {
return unitName;
}
}
Here the values "xyz" is stored in unitName and doesnot get updated again when you change to "zxy".
MyDs MyDsObj = MyDs.getMyDsObject("xyz");
Log.i("value", "" + MyDsObj.getUnitName());
MyDs MyDsObj1 = MyDs.getMyDsObject("zxy");
Log.i("value",""+MyDsObj.getUnitName());
Well, you question is not really clear (and the comment section is really chaty...), but if you want to only be able to set a value once but not during the initialisation, setters are not a bad choice. Just add a constraint.
public class MyClass{
private static final String DEFAULT_VALUE = new String("");
private String value = DEFAULT_VALUE;
public final void setValue(String value){
if(this.value != DEFAULT_VALUE) //use the reference on purpose
throw new IllegalArgumentException("This value can't be changed anymore");
this.value = value;
}
// Don't return `DEFAULT_VALUE` to prevent someone to gain access to that instance
public final String getValue(){
return this.value == DEFAULT_VALUE ? null : this.value;
}
}
This will be done at runtime, but this would do the trick.
Now, this is an immutable instance, with some mutable instance you might want to do a copy of it to be sure it can't be modifier using the original reference.

Duplicate and add fields between classes

I was wondering if the following scenario is possible.
Having two classes (Source and Destination) where in code I could do this:
public class Source{
private String fieldA;
private String fieldB;
public Source(){ ... }
}
...
public class Destination{
public Destination(Source src){ ... }
}
Source src = new Source();
Destination dest = new Destination(src);
dest.fieldA = "test";
dest.fieldB = "test";
So what I mean here is that I have two classes, one called Source that contains (private) fields and one called Destination with no fields. After creating two objects of these classes and passing in Source into the constructor of Destination, I want to be able to duplicate/copy the fields of Source into Destination.
Could something like this be possible in Java, whether or not using Reflection? And if possible, can someone give me a minor example I can start with.
A hackish version to accomplish this is to add all fields to a Map. The fields can be copied from the source object to the destination object and the field name can be the key. Something along the lines of this:
public class FieldAccessor {
public static class Destination {
private final Map<String, Object> fields = new HashMap<>();
public Destination(Object o) {
final Set<Field> accessibleFields = Arrays.stream(o.getClass().getDeclaredFields())
.map(field -> {
field.setAccessible(true);
return field;
})
.collect(Collectors.toSet());
accessibleFields.forEach(field -> {
try {
fields.put(field.getName(), field.get(o));
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unable to access field", e);
}
});
}
public Set<String> fieldNames() {
return fields.keySet();
}
public Optional<Object> fieldValue(String fieldName) {
return Optional.ofNullable(fields.get(fieldName));
}
}
public static class Source {
private final String fieldA;
private final Integer fieldB;
private final int fieldC;
public Source(String fieldA, Integer fieldB, int fieldC) {
this.fieldA = fieldA;
this.fieldB = fieldB;
this.fieldC = fieldC;
}
public String getFieldA() {
return fieldA;
}
public Integer getFieldB() {
return fieldB;
}
public int getFieldC() {
return fieldC;
}
}
#Test
public void testFields() {
Destination destination = new Destination(new Source("Abc", 123, 456));
destination.fieldNames().stream().forEach(fieldName -> {
System.out.println("Fieldname: " + fieldName + ", value: " + destination.fieldValue(fieldName).get());
});
}
}
For more info, check out this SO.
However, this is not something I would use in real production code. Instead, I would use some sort of serialization by e.g. using Jackson.
So you want to dynamically create fields in an object ? That's not directly possible in Java. If you just wanted to copy methods of an interface, the answer would have be to use a JDK proxy. It may still be of interest if :
you accept to only use getters and setters in Destination class
Source class implements an interface defining the setters and getters you want to copy
If you cannot accept those restrictions, you will have to look to CGLIB proxies or Javassist, that is libraries that dynamically modify the bytecode of the compiled class objects at load time. It is a really advanced feature, that is mainly used in frameworks or other libraries and not in high-level programs. Typically it is used in Object Relational Mappers like Hibernate to replace simple collection classes with enhanced ones that transparently gets (an save) their elements in database.
In any other case, trying to access private fields outside of the class should be seen as an indicator for a possible design flaw. private means implementation dependant and can change across versions and should not be used without knowing why.
The simplest and most efficient way to do it is copying the fields explicitly :
public Destination(Source src)
{
this.fieldA = src.getFieldA();
this.fieldB = src.getFieldB();
}
I don't see the point in using reflection for this purpose.
The only thing is in my mind for this at this time is extending Destination class from Source
public class Source{
private String fieldA;
private String fieldB;
//You need to have both Getter and Setter for fieldA and fieldB
public Source(){ ... }
}
...
public class Destination extends Source{
public Destination(){...}
}
Source src = new Destination();
dest.setFieldA("test");
dest.setFieldB("test");
Private members of Source cannot be accessed from Destination object even if you are passing a Source object to Destination.
You need to add string fieldA, fieldB to Destination to
string fieldA, fieldB;
public Destination(Source src)
{
fieldA = src.fieldA;
fieldB = src.fieldB;
}

Lookup within the enum constants by constant specific data [duplicate]

This question already has answers here:
How to retrieve Enum name using the id?
(11 answers)
Closed 9 years ago.
I need to do look up in an enum by an int . The enum is as folows :
public enum ErrorCode{
MissingReturn(1,"Some long String here"),
InvalidArgument(2,"Another long String here");
private final int shortCode ;
private final String detailMessage;
ErrorCode(shortCode ,detailMessage){
this.shortCode = shortCode ;
this.detailMessage= detailMessage;
}
public String getDetailedMessage(){
return this.detailMessage;
}
public int getShortCode(){
return this.shortCode ;
}
}
Now Is need to have a lookup method that would take an int code and should return me the String message pertaining to that code that is stored in the Enum.Passing a "1" should return me the String "Some long String here". What is the best way to implement this functionality?
public static String lookUpMessageFromCode(int code){
}
P.S: Is the class EnumMap useful for this kind of use case? If yes,please let me know why?
Depending on the int values that you associated with your enum, I would add a static array of ErrorCodes, or a static Map<Integer,ErrorCode> to your enum class, and use it to do a lookup in the message from code method. In your case, an array is more appropriate, because you have values 1 and 2 which are small. I would also change the signature to return ErrorCode.
private static final ErrorCode[] allErrorCodes = new ErrorCode[] {
null, MissingReturn, InvalidArgument
};
public static ErrorCode lookUpByCode(int code) {
// Add range checking to see if the code is valid
return allErrorCodes[code];
}
The callers who need the message would obtain it like this:
String message = ErrorCode.lookUpByCode(myErrorCode).getDetailedMessage();
I would simply iterate through your Enum values and check the code. This solution lets you utilize the existing Enum with out creating another object to manage.
public enum ErrorCode {
MissingReturn(1, "Some long String here"),
InvalidArgument(2, "Another long String here");
private final int shortCode;
private final String detailMessage;
ErrorCode(int shortCode, String detailMessage) {
this.shortCode = shortCode;
this.detailMessage = detailMessage;
}
public String getDetailedMessage() {
return this.detailMessage;
}
public int getShortCode() {
return this.shortCode;
}
public static String lookUpMessageFromCode(int code) {
String message = null;
for (ErrorCode errorCode : ErrorCode.values()) {
if (errorCode.getShortCode() == code) {
message = errorCode.getDetailedMessage();
break;
}
}
return message;
}
public static void main(String[] args) {
System.out.println(ErrorCode.lookUpMessageFromCode(1));
System.out.println(ErrorCode.lookUpMessageFromCode(2));
}
}
One thing to note
The Enum constructor is missing the type information regarding its parameters.
ErrorCode(int shortCode, String detailMessage) {
this.shortCode = shortCode;
this.detailMessage = detailMessage;
}
Here is another option:
public static String lookUpMessageFromCode(int code){
for(ErrorCode ec:ErrorCode.values()){
if(ec.shortCode==code)
return ec.detailMessage;
}
return null;
}

Categories

Resources