0

I am working on a web project using Spring and Spring MVC.

I have a feature that is the same for 3 different elements (which are available in dropdown in view). Only two parameters change for each item. I decided to put these elements and parameters in a .properties file to permit the user change them. So for example in my .properties I have the following:

FC
fcUuid=11111111111111111
fcTag=tag1

AC
itUuid=22222222222222222
itTag=tag2

IT
acUuid=333333333333333333
acTag=tag3

For the moment I am able to retrieve each element separately.

For example:

 String communityUuid = SpringPropertiesUtil.getProperty("fcUuid");

(SpringPropertiesUtil extends PropertyPlaceholderConfigurer)

But my question is: how can I retrieve all the parameters relative to one element?

For example the user selects "FC", how in my service layer can I retrieve both fcUuid and fcTag parameters?

Of course I can do something like:

 if(param="FC"){
     String communityUuid = SpringPropertiesUtil.getProperty("fcUuid");
     String communityTag = SpringPropertiesUtil.getProperty("fcTag");
 } else if (param="AC"){...}

But I don't want to do that because the user can add elements so I would have to modify the code each time.

I would like something like:

String communityUuid = SpringPropertiesUtil.getProperties(param[0]);
String tagUuid = SpringPropertiesUtil.getProperties(param[1]);

Or even better:

String communityUuid = SpringPropertiesUtil.getProperties(param[uuid]);
String tagUuid = SpringPropertiesUtil.getProperties(param[tag]);
Héloïse Chauvel
  • 502
  • 3
  • 6
  • 21
  • https://stackoverflow.com/questions/23506471/spring-access-all-environment-properties-as-a-map-or-properties-object check this to get all properties by mask – StanislavL Jul 18 '17 at 09:35
  • Actually I had already transfromed my file into hashmap in my `SpringPropertiesUtil`class, that's what permit me to get one property at a time. But how it can help for my situation? – Héloïse Chauvel Jul 18 '17 at 11:57
  • You can go through all the map keys and check whether a key startsWith desired prefix and return it – StanislavL Jul 18 '17 at 12:27

2 Answers2

1

You need customize how to handle properties into map that you need. You can do like :

#group your properites  
uiValues=\
  FC={fcUuid:11111111111111111},{fcTag : tag1}&&\
  AC={itUuid : 22222222222222222},{itTag : tag2}&&\
  IT={acUuid:333333333333333333},{acTag:tag3}


@Component
public class ConfigProperties {
    //FC=...&&AC=....&&IT=....
    private static final String GROUP_SPLITTER = "&&";
    private static final String GROUP_VALUES_MARKER = "=";
    private static final String START_VALUES_IN_GROUP = "{";
    private static final String END_VALUES_IN_GROUP = "}";
    private static final String VALUES_SPLITTER= ",";
    private static final String KEY_VALUE_SPLITTER= ":";

        @Value("#{T(current current package .ConfigProperties).
                  decodeMap('${uiValues}')}")
        private Map<String,Values> map;

        /**
         if(param="FC"){
         String communityUuid = SpringPropertiesUtil.getProperty("fcUuid");
         String communityTag = SpringPropertiesUtil.getProperty("fcTag");
         }
         @Autowired
         ConfigProperties configProperties;

         String communityUuid = configProperties.getValue("FC","fcUuid");
         String communityTag = configProperties.getValue("FC","fcTag");
         */
        public String getValue(String key , String property){
            //add check for null
            Values values= map.get(key);
            if (values == null){
                return "";
            }
            for (Tuple tuple : values.tuples){
                if (tuple.key.equals(property)){
                    return tuple.value;
                }
            }
            return "";
        }

        public List<String> getProperties(String key){
            //add check for null
            List<String> properties = new ArrayList<>();
            Values values= map.get(key);
            //add check for null
            for (Tuple tuple : values.tuples){
                properties.add(tuple.key);
            }
            return properties;
        }

        public static Map<String, Values> decodeMap(String value) {
            //add validator for value format
            boolean isValid = true;
            if(!isValid){
                return new HashMap<>();
            }
            Map<String, Values> map = new LinkedHashMap<>();
            String[] groups = value.split(GROUP_SPLITTER);
            for (String group : groups) {

                String[] values = splitToKeyAndValues(group.split(GROUP_VALUES_MARKER)[1]);
                String key = group.substring(0,group.indexOf(GROUP_VALUES_MARKER));
                map.put(key, getValues(values));
            }
            return map;
        }

        private static Values getValues(String[] parts) {
            Values values = new Values();
            for (int i=0;i<parts.length;i++){
                values.tuples.add(getTuple(parts[i]));
            }
            return values;
        }

        private static Tuple getTuple(String parts) {
            Tuple tuple = new Tuple();
            parts = parts.substring(1,parts.length()-1);
            tuple.key= parts.split(KEY_VALUE_SPLITTER)[0];
            tuple.value= parts.split(KEY_VALUE_SPLITTER)[1];
            return tuple;
        }

        static String[] splitToKeyAndValues(String valuesInGroup) {
            return valuesInGroup.split(VALUES_SPLITTER);
        }
    }

    class Values{
        List<Tuple> tuples = new ArrayList<>();
    }
    class Tuple{
        String key;
        String value;
    }
xyz
  • 5,228
  • 2
  • 26
  • 35
  • Interesting approach, the problem is that you transformed the `.properties` file into String variable before transforming it into Hashmap. I'd rather kept the data intact and transform it directly to Hashmap. I've managed to do it, I'll post my answer this afternoon (Paris UTC Time). – Héloïse Chauvel Jul 19 '17 at 09:51
  • There are many ways how you can do it.i did it as it's properties. In many case i said as it property then work with it as value.i can inject in wher i need as value or use as component and inject it but my case i need my own format – xyz Jul 19 '17 at 10:15
0

With the help of one of my colleagues I managed to realize that. This is how I proceeded:

  • In my .properties file I changed the data format, now it looks like:

    #FC
    clientApplications[0].name=FC
    clientApplications[0].communityId=00000000000000
    clientApplications[0].tag=tag0
    
    #AC
    clientApplications[1].name=AC
    clientApplications[1].communityId=11111111111111
    clientApplications[1].tag=tag1
    
    etc...
    
  • I created a bean named ClientApplication (FC, AC and IT are applications) with 3 attributes (name, communityId and tag)

  • I created a class named ApplicationStore that stores all the applications present in the propertiesfile in the form of ClientApplication objects and that provides a get method which returns a ClientApplication according to the name of the app.

    @Component("applicationStore")
    public class ApplicationStore {     
    
        private Map<String, ClientApplication> map;
    
        public void put(String key, ClientApplication value) {
            map.put(key, value);
        }
    
        public ClientApplication get(String key) {
            return map.get(key);
        }
    
        public ApplicationStore() {
            int i = 0;
            map = new HashMap<String, ClientApplication>();
    
            while (SpringPropertiesUtil.getProperty("clientApplications[" + i + "].name") != null) {
                ClientApplication ca = new ClientApplication();
                ca.setName(SpringPropertiesUtil.getProperty("clientApplications[" + i + "].name"));
                ca.setCommunityId(SpringPropertiesUtil.getProperty("clientApplications[" + i + "].communityId"));
                ca.setTag(SpringPropertiesUtil.getProperty("clientApplications[" + i + "].tag"));
    
                map.put(ca.getName(), ca);
    
                i++;
            }
        }
    }
    
  • With that I only have to add this to my service layer:

    @Service("aService")
    public class AServiceImpl implements AService {    
        @Autowired
        private ApplicationStore apps;
    
        private String communityUuid;
        private String communityTag;
    
        @Override
        public void aMethod(String appName) trhows Exception {
            ClientApplication ca = new ClientApplication();
            ca = apps.get(appName);
            communityUuid = ca.getCommunityId();
            communityTag = ca.getTag();
    
            System.out.println("Application for key " + app + " : " + ca);
            System.out.println("communityUuid: " + communityUuid);
            System.out.println("communityTag:" + communityTag);
        }
    }
    
Héloïse Chauvel
  • 502
  • 3
  • 6
  • 21